How PrecompileTools works

Julia itself has a function precompile, to which you can pass specific signatures to force precompilation. For example, precompile(foo, (ArgType1, ArgType2)) will precompile foo(::ArgType1, ::ArgType2) and all of its inferrable callees. Alternatively, you can just execute some code at "top level" within the module, and during precompilation any method or signature "owned" by your package will also be precompiled. Thus, base Julia itself has substantial facilities for precompiling code.

The workload macros

@compile_workload adds one key feature: the non-inferrable callees (i.e., those called via runtime dispatch) that get made inside the @compile_workload block will also be cached, regardless of module ownership. In essence, it's like you're adding an explicit precompile(noninferrable_callee, (OtherArgType1, ...)) for every runtime-dispatched call made inside @compile_workload.

These workload macros add other features as well:

  • Statements that occur inside a @compile_workload block are executed only if the package is being actively precompiled; it does not run when the package is loaded, nor if you're running Julia with --compiled-modules=no.
  • Compared to just running some workload at top-level, @compile_workload ensures that your code will be compiled (it disables the interpreter inside the block)
  • PrecompileTools also defines @setup_workload, which you can use to create data for use inside a @compile_workload block. Like @compile_workload, this code only runs when you are precompiling the package, but it does not necessarily result in the @setup_workload code being stored in the package precompile file.

@recompile_invalidations

@recompile_invalidations activates logging of invalidations before executing code in the block. It then parses the log to extract the "leaves" of the trees of invalidations, which generally represent the top-level calls (typically made by runtime dispatch). It then triggers their recompilation. Note that the recompiled code may return different results than the original (this possibility is why the code had to be invalidated in the first place).