Last active
July 28, 2021 18:01
Flame graph visualization for Octave's profiler output.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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