Roadmap for a faster time-to-first-plot?

I’m a bit confused what’s changed. In Julia v0.5 or so I used SnoopCompile on all tests to generate precompiles and this worked quite well. Then at some point the precompiles stopped showing any noticeable improvement and I deleted the precompiles.

But now you are saying use SnoopCompile To generate precompile statements, but not on the tests?

It never really changed. It just has to do with how much gets invalidated and how much of it can be isolated to specific packages. Precompiles which “share types” are currently just dropped (probably one of the biggest limitations to even using something like SnoopCompile)

We need to time more, but my feeling is that if Gadfly/Compose and Plots both dropped their dependency on Measurements.jl and instead embedded a version into themselves as a package so that all of those weird number types can precompile and then a snoop file is used for that, I think it could do quite a bit.

(In fact, if anyone wants to contribute, this is a very nice thing to try. Make Measurements.jl a submodule of Plots by pasting it in, and use the SnoopCompile stuff from Leon’s PR to add precompiles that utilize this module. See what happens. Beginner friendly!)


I guess this can be done with just a few lines, without copying the whole codebase?

include(Base.locate_package(Base.PkgId(Base.UUID("eff96d63-e80a-5855-80a2-b1b0885c5ab7"), "Measurements")))
using .Measurements  # notice the leading dot

(Note that, strictly speaking, this requires Measurements.jl to make deps a part of public API.)

Are you talking about


Yes Measures

You don’t really have to do any diving now with @snoopi. The old @snoopc measured codegen time (dominated by LLVM time), which isn’t terribly relevant. With @snoopi you both measure inference time and can then figure out how well your intervention “worked.”


It’s already in a submodule so this should be very easy


I just tried that and could not notice any significant change.


julia> @time using Plots
11.759940 seconds (22.34 M allocations: 1.123 GiB, 3.96% gc time)

julia> @time display(plot(rand(10)))
Plot{Plots.GRBackend() n=1}
14.330170 seconds (28.71 M allocations: 1.385 GiB, 3.41% gc time)


(with code from Measures.jl copied into a submodule of Plots)

julia> @time using Plots
 12.408045 seconds (22.58 M allocations: 1.137 GiB, 4.08% gc time)

julia> @time display(plot(rand(10)))
Plot{Plots.GRBackend() n=1}
 14.317090 seconds (28.69 M allocations: 1.384 GiB, 3.63% gc time)

GR now contains a snoop function that can be used to minimize time-to-first-plot:

julia -e 'using PackageCompiler; compile_incremental("GR", joinpath(pwd(), "snoop.jl"), cc_flags="-mtune=\"generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)\"")'
time julia snoop.jl

The results are OK for me:

Build shared library "/usr/local/lib/julia/packages/PackageCompiler/CJQcs/sysimg/sys.dylib":

`cc -shared '-DJULIAC_PROGRAM_LIBNAME="/usr/local/lib/julia/packages/PackageCompiler/CJQcs/sysimg/sys.dylib"' -o /usr/local/lib/julia/packages/PackageCompiler/CJQcs/sysimg/sys.dylib -Wl,-all_load /usr/local/lib/julia/packages/PackageCompiler/CJQcs/sysimg/sys.a -std=gnu99 -I/usr/local/Applications/ -DJULIA_ENABLE_THREADING=1 -fPIC -L/usr/local/Applications/ -Wl,-rpath,/usr/local/Applications/ -Wl,-rpath,/usr/local/Applications/ -ljulia -m64 -O3 '-mtune="generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)"' -Wl,-install_name,@rpath//usr/local/lib/julia/packages/PackageCompiler/CJQcs/sysimg/sys.dylib`

real 0m1.166s
user 0m0.655s
sys 0m0.524s

I have a similar script for the Plots + GR combination, which I can provide, if desired …


:man_shrugging: thanks for trying it!


There’s a significant change for Plots + GR:

% time julia snoop-Plots.jl
julia snoop-Plots.jl  33.29s user 1.16s system 101% cpu 34.065 total

… compared with a “package-compiled” sysimg:

% time julia snoop-Plots.jl
julia snoop-Plots.jl 0.92s user 0.34s system 95% cpu 1.323 total

snoop-Plots.jl is a mix of plain GR and basic Plots functions.

The speedup is ~ 35x.