This is a bit of a stylistic “what’s the most elegant way to do this?” question than a functionality question. Basically, let’s say we have a script that runs some computation and saves some outputs for us, and we’re currently working on developing the script. Here’s my example:
using Base.Threads: @threads
# block of computation
res = Vector{Float32}(undef, 1_000)
@threads for i in 1:1_000
sleep(0.01) # something in here takes a while to run
res[i] = 42
end
# output the results of the computation (maybe something like save to file in practice)
println("The results is $(join(res[1:10], ','))...")
Now, to aid in optimizing the script, I want to profile the parallelized loop in the middle and look at a flame graph. To do this, I could edit the script to remove threading and enclose the key loop in @profile(...)
like this:
import ProfileSVG
using Profile: @profile, Profile
# using Base.Threads: @threads
Profile.clear()
res = Vector{Float32}(undef, 1_000)
@profile(
# block of computation
for i in 1:1_000
sleep(0.01) # something in here takes a while to run
res[i] = 42
end
)
ProfileSVG.save("flamegraph.svg")
# output the results of the computation (maybe something like save to file in practice)
println("The results is $(join(res[1:10], ','))...")
But then I’d have to change the script to toggle profiling. I am looking for a better way, something like having the script look for an environment variable and profile conditionally on that. I thought I should reach out to see if folks in the community have tips for a better workflow they could share. Maybe there is some syntactic magic for conditionally enabling/disabling the @profile
and @threads
macros? I’m thinking the ideal approach would look something like this:
import ProfileSVG
using Profile: @profile, Profile
using Base.Threads: @threads
const IS_PROFILED = get(ENV, "PROFILE_THE_SCRIPT", false)
Profile.clear()
res = Vector{Float32}(undef, 1_000)
@profile(;disable=!IS_PROFILED)(
# block of computation
@threads(;disable=IS_PROFILED) for i in 1:1_000
sleep(0.01) # something in here takes a while to run
res[i] = 42
end
)
if IS_PROFILED
ProfileSVG.save("flamegraph.svg")
end
# output the results of the computation (maybe something like save to file in practice)
println("The results is $(join(res[1:10], ','))...")
But maybe there’s also just a much better workflow for occasionally profiling a script you’re developing to keep a sense of what parts are slow and catch performance-killing mistakes? All suggestions are greatly appreciated!