I did not find an example of querying Julia profiling data for e.g. the number of samples that hit a given function. I want to post what I’m using in case it’s useful to anyone searching:
using Profile
using FlameGraphs
using FlameGraphs.AbstractTrees: PreOrderDFS
# ----------------
function foo(n)
acc = 0.0
for i = 1:n
if i % 2 == 0
acc += bar1(i)
else
acc += bar2(i)
end
end
return acc
end
baz(x) = sqrt(sin((cos(sin(tan(cos(sin(x))))))^2))
function bar1(n)
acc = 0.0
for i=1:n
acc += baz(i)
end
return acc
end
function bar2(n)
acc = 0.0
for i=1:(2n)
acc += baz(i)
end
return acc
end
# ----------------
function groupby_sf(fg)
d = Dict()
for node in PreOrderDFS(fg)
push!(get!(d, node.data.sf, []), node)
end
return d
end
function find_sf_keys_by_func(gsf, func::Symbol)
filter(sf -> func == sf.func, collect(keys(gsf)))
end
function time_in_function(gsf, f::Symbol)
ks = find_sf_keys_by_func(gsf, f)
ns = reduce(vcat, getindex.(Ref(gsf), ks))
spans = map(n -> n.data.span, ns)
return sum(length.(spans))
end
profile_fill_ratio() = Profile.len_data() / Profile.maxlen_data()
Profile.init(;delay=0.001)
@profile foo(5000)
@show profile_fill_ratio()
# VSCodeServer.view_profile() # use visualization in VS Code
fg = FlameGraphs.flamegraph() # retreieves current profiling data
gsf = groupby_sf(fg)
@show time_in_function(gsf, :foo)
@show time_in_function(gsf, :bar1)
@show time_in_function(gsf, :bar2)
@show time_in_function(gsf, :baz)
profile_fill_ratio() = 0.0086456
time_in_function(gsf, :foo) = 1551
time_in_function(gsf, :bar1) = 539
time_in_function(gsf, :bar2) = 1010
time_in_function(gsf, :baz) = 1532