Instantly share code, notes, and snippets.

Embed
What would you like to do?
Flame graph visualization for Octave's profiler output.
function flamegraph(profdata)
### project: flamegraph
### authors: Christian Himpe (0000-0003-2194-6754)
### version: 0.1 (2019-01-06)
### license: BSD-2-Clause (opensource.org/licenses/BSD-2-Clause)
### summary: Flame graph visualization for Octave's profiler output.
#
# USAGE:
#
# profiler on;
# mycode;
# profiler off;
# profdata = profiler("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.
# * Requires large amounts of memory.
# * Why does gnuplot work better than fltk backend (set via graphics_toolkit)?
#
# KEYWORDS: runtime, stacktrace, profile, performance, optimization
depth = traverse(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
annotation("textbox", ...
[start,(level-1)/depth,reldur(k),1/depth], ...
"String",strrep(ftable{fmap{k}},"__",""), ...
"Color","b", ...
"BackgroundColor",cmap(level,:), ...
"FitBoxToText","Off", ...
"Interpreter","none");
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 d = traverse(tree)
subtree = {tree.Children};
l = zeros(1,numel(subtree));
for k = 1:numel(subtree)
l(k) = traverse(subtree{k}) + 1;
endfor
if(numel(subtree)==0)
d = 1;
else
d = max(l);
endif
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment