Package compilation woes



Here’s the situation:

  • I have the HTTP.jl package, which includes a decent amount of fairly modular code
  • Without any tricks, package compilation takes 7 seconds, using takes 0.7 s, and making a first request takes 5 whole seconds
  • Trying SnoopCompile.jl didn’t actually seem to make any difference (maybe I’m using it wrong? Branch is here)
  • I also tried putting a block just after my HTTP definition like:

but that didn’t seem to make any difference either.

  • The option I’m considering going w/ is putting the above try-block in the module __init__(); that balloons the using time to 10s, which is painful to have to pay every single time you do using HTTP, but in a production setting, I think it’s the only option vs. having the first request/response take 5 whole seconds to compile/process

Anybody have any other ideas? Feeling a little stuck here.


I have no good idea how to solve this, but I think sticking it into __init()__ would be really problematic: now any package that depends on HTTP.jl will have those 10s added when someone loads that third package via using Foo, even if the user of Foo actually never intends to use functionality in Foo.jl that depends on HTTP.jl.


If that helps make the case and light the fire for figuring out a real solution to conditional package dependencies then I’m in! But seriously, we can’t keep dancing around this issue forever, adding weird workarounds and hacks, if it takes making a bunch of packages really painful, then it can only help prioritize the work to figure out a solution.

Even so, it’s simply unacceptable in any kind of production setting to have the first request/response take 5 seconds to process; it’s much better to require any compilation happen at package load time. Granted, these “production apps” could be the ones to put their own “warm up” code in their own __init__(), but that’s easy to forget and a hassle. There’s just not a great solution to these issues right now as far as I can tell.


Can we do any kind of profiling of where that 5 seconds in the initial get is actually being spent? It seems weird since there isn’t that much Julia code being compiled for get.


You have a typo in your SnoopCompile branch. You’re including precompile_Base.jl 4 times over. Fixing that might help, but also from the SnoopCompile README:

Currently, precompilation does not cache functions from other modules; as a consequence, your speedup in execution time might be smaller than you’d like. In such cases, one strategy is to generate a script for your base/userimg.jl file and build the packages (with precompiles) into julia itself.

So the precompile statements for modules other than HTTP aren’t really winning you anything.


I’ve experimented with SnoopCompile for my own packages and found the gain is modest at best, so it doesn’t surprise me that it isn’t helping here much.


I hope that this issue gets some attention. I have code where type inference lasts longer than a minute and don’t have an idea how to reduce it. Can’t share the code unfortunately.


Oh but there kind of is… It’s a behemoth 1000+ line function, ported from C.


Update: spent a decent amount of time this morning digging in to some solutions and made some progress. Turns out the precompile statements generated from SnoopCompile weren’t even valid, but seemed to assume some old call convention; ensuring each precompile statement was valid seems to have helped decently. I now see initial package compilation times between 10-20s, w/ subsequent package using HTTP down to 2.5-3s (just a hair more than w/o the precompile statements), and the initial HTTP.get request is down to 3s (from 6s).

I’ve also opened an issue here to gather some feedback/answers to additional things I came across in my journey to understanding precompile. Hopefully the answers/feedback there will continue to improve the situation, but for now, I at least think the situation is much more reasonable than it was.


Hi @quinnj, how is this all going? Do you have anything that’s ready to be tested?