Skip to content

Instantly share code, notes, and snippets.

@gramian
Last active July 28, 2021 18:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gramian/7807c670588d10adbfca9add73daeda2 to your computer and use it in GitHub Desktop.
Save gramian/7807c670588d10adbfca9add73daeda2 to your computer and use it in GitHub Desktop.
Flame graph visualization for Octave's profiler output.
function flamegraph(profdata)
### project: flamegraph
### authors: Christian Himpe (0000-0003-2194-6754)
### version: 0.3 (2021-02-06)
### license: BSD-2-Clause (opensource.org/licenses/BSD-2-Clause)
### summary: Flame graph visualization for Octave's profiler output.
#
# USAGE:
#
# profile on;
# mycode;
# profile off;
# profdata = profile("info");
# flamegraph(profdata);
#
# DESCRIPTION:
#
# Simple recursive implementation of the flame graph visualization of
# profile analysis and statistics for Octave >= 4.2.
#
# Based on the flame graph profile visualization by Brendan Gregg, see:
# http://www.brendangregg.com/flamegraphs.html for further details and:
#
# B. Gregg. "The Flame Graph", ACM Queue (Cloud Debugging) 14(2): 1--28, 2016.
# doi:10.1145/2927299.2927301
#
# NOTE:
#
# This function is designed specficially for the profiler output of GNU Octave
# and is incompatible with the Mathworks MATLAB profiler output.
#
# TODO:
#
# * Text is overlapping for thin flames.
# * Why does gnuplot work better than fltk backend (set via graphics_toolkit)?
#
# KEYWORDS: runtime, stacktrace, profile, performance, optimization
depth = tree_depth(profdata.Hierarchical);
cmap = hot(depth);
ftable = {profdata.FunctionTable.FunctionName};
function l = dissect(tree,start,width,level)
subtree = {tree.Children};
reldur = cell2mat({tree.TotalTime});
seldur = cell2mat({tree.SelfTime});
totdur = sum(reldur);
reldur /= totdur;
seldur /= totdur;
reldur *= width;
seldur *= width;
fmap = {tree.Index};
[~,ind] = sort(reldur,'descend');
for k = ind
patch(start + reldur(k) .* [0, 1, 1, 0], ...
(level + [-1, -1, 0, 0])./depth, ...
'FaceColor',cmap(level,:));
text(start+0.5*reldur(k), ...
(level-0.5)/depth, ...
strrep(ftable{fmap{k}},"__",""), ...
'Color','blue');
dissect(subtree{k},start+0.5*seldur(k),reldur(k)-seldur(k),level+1);
start += reldur(k);
endfor
endfunction
figure;
axis off;
dissect(profdata.Hierarchical,0.01,0.98,1);
endfunction
function depth = tree_depth(tree,accum)
if 1 == nargin
accum = 0;
endif
subtree = {tree.Children};
if 0 == numel(subtree)
depth = accum;
else
depth = max(cellfun(@(k) tree_depth(k,accum + 1),subtree));
endif
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment