# PackageCompiler.jl: What is it doing and how do I use it correctly?

**URL:** <https://discourse.julialang.org/t/packagecompiler-jl-what-is-it-doing-and-how-do-i-use-it-correctly/135530>\
**Category:** General Usage\
**Tags:** precompilation, package-compiler\
**Created:** [February 7, 2026, 8:07pm UTC](https://discourse.julialang.org/t/packagecompiler-jl-what-is-it-doing-and-how-do-i-use-it-correctly/135530 "2026-02-07T20:07:28Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [February 7, 2026, 8:07pm UTC](https://discourse.julialang.org/t/packagecompiler-jl-what-is-it-doing-and-how-do-i-use-it-correctly/135530/1 "2026-02-07T20:07:28Z")

</div>

Today I was playing with PackageCompiler.jl (PC) because I am wondering whether it could play a role in reducing startup times (sparked by the recent discussions about the worsening of Julia startup times [ref](https://discourse.julialang.org/t/new-julia-versions-higher-pluto-loading-times/135187)). During my experiments, I realized that PC does not do what I expected and hope that some of you can shed some light on this 🙂

# Setup

> **versioninfo & envs**
>
> ```julia-auto
> julia> versioninfo()
> Julia Version 1.12.4
> Commit 01a2eadb047 (2026-01-06 16:56 UTC)
> Build Info:
> Official https://julialang.org release
> Platform Info:
> OS: Linux (x86_64-linux-gnu)
> CPU: 16 × AMD Ryzen 7 4800H with Radeon Graphics
> WORD_SIZE: 64
> LLVM: libLLVM-18.1.7 (ORCJIT, znver2)
> GC: Built with stock GC
> Threads: 1 default, 1 interactive, 1 GC (on 16 virtual cores)
> 
> (@v1.12) pkg> st
> Status `~/.julia/environments/v1.12/Project.toml`
> [6e4b80f9] BenchmarkTools v1.6.3
> [5fb14364] OhMyREPL v0.5.32
> [295af30f] Revise v3.13.2
> 
> (@packagecompiler) pkg> st
> Status `~/.julia/environments/packagecompiler/Project.toml`
> [9b87118b] PackageCompiler v2.2.4
> 
> ```

Generally, my goal was to improve the startup time of my standard REPL (so REPL + startup.jl + packages in default env which are Revise.jl, OhMyRepl.jl and BenchmarkTools.jl). Additionally, I wanted a smooth UX and not have common operation lag a bit on first occurence, like pressing a key, printing an error, using `Pkg.status()`. So I created a precompile file with `julia --trace-compile compile-file`, played around the REPL a bit and then used this to create a sysimage:

```julia-auto
$ time julia -q -e 'Pkg.activate("packagecompiler";shared=true);import PackageCompiler;PackageCompiler.create_sysimage(;project=".julia/environments/v1.12/",sysimage_path="julia/v12-sysimg5",precompile_statements_file="compile-file-final")'
  Activating project at `~/.julia/environments/packagecompiler`
✔ [03m:32s] PackageCompiler: compiling incremental system image

real	4m24.571s
user	17m53.056s
sys	0m21.353s

```

# Question 1: What exactly is in the sysimage?

I have a bit of knowledge about image-based systems from SBCL and thus thought that a Julia sysimage is the same as a SBCL image created by [`(save-lisp-and-die)`](https://www.sbcl.org/manual/#Function-sb_002dext-save_002dlisp_002dand_002ddie). That would include essentially the whole global state. This seems not to be the case though because my custom sysimage still needs to do `import Pkg` before I can use Pkg.

# Question 2: Why does sysimage creation take ~5min?

Maybe the answer to the previous question explains this as well. What is PC doing? I used the default `incremental=true`, so in my mind PC basically just needs to dump the current image. Maybe perform a bit of additional precompilation for additional precompile statements/workloads. But even if it needs to precompile the loaded packages again, that shouldn’t take 5mins (maybe more like 1-2min I think). For reference, SBCL takes 2 seconds to dump the image:

```julia-auto
$ time sbcl --noinform --eval '(sb-ext:save-lisp-and-die "test-sbcl-image")'

real	0m1.729s
user	0m1.546s
sys	0m0.183s

```

Bonus question: Since PC clearly does not ‘just dump the image’, would dumping the image more directly be possible for Julia as well?

# Question 3: Why do I still get a lot of output from --trace-compile?

If I start Julia with my custom sysimage and `--trace-compile` and do the same rudimentary options as before, I still get almost as much output as before. I thought using the precompile file would include the code into the sysimage such that it does not get compiled again?

# Question 4: Why are some of the operations still slow?

Probably related to the previous question. Creating the custom sysimage did not remove the lag for some operations:

- first button press has no longer noticeable lag
- Pkg.status() still has lag
- first error message printed still has lag

While startup indeed got faster:

```julia-auto
$ hyperfine 'julia -e "exit()"' 'julia --sysimage julia/v12-sysimg5 -e "exit()"'
Benchmark 1: julia -e "exit()"
  Time (mean ± σ): 1.147 s ± 0.013 s [User: 1.651 s, System: 0.236 s]
  Range (min … max): 1.126 s … 1.166 s 10 runs
 
Benchmark 2: julia --sysimage julia/v12-sysimg5 -e "exit()"
  Time (mean ± σ): 423.9 ms ± 17.3 ms [User: 990.1 ms, System: 193.6 ms]
  Range (min … max): 409.7 ms … 471.0 ms 10 runs
 
Summary
  julia --sysimage julia/v12-sysimg5 -e "exit()" ran
    2.71 ± 0.11 times faster than julia -e "exit()"

```

However using `Pkg.status()` is actually _slower_

```julia-auto
$ hyperfine 'julia -e "Pkg.status()"' 'julia --sysimage julia/v12-sysimg5 -e "Pkg.status()"'
Benchmark 1: julia -e "Pkg.status()"
  Time (mean ± σ): 1.630 s ± 0.034 s [User: 2.567 s, System: 0.314 s]
  Range (min … max): 1.573 s … 1.697 s 10 runs
 
Benchmark 2: julia --sysimage julia/v12-sysimg5 -e "Pkg.status()"
  Time (mean ± σ): 1.861 s ± 0.022 s [User: 3.297 s, System: 0.335 s]
  Range (min … max): 1.832 s … 1.890 s 10 runs
 
Summary
  julia -e "Pkg.status()" ran
    1.14 ± 0.03 times faster than julia --sysimage julia/v12-sysimg5 -e "Pkg.status()"

```

Does that make sense to anybody?

How do I use PC correctly such that these operations no longer lag? Or am I misunderstanding PC and what it can do fundamentally?

So if someone could enlighten me or point me to resources that contain answers, I would be very thankful 🙂  
EDIT: A thought that came to my mind just after posting: Maybe REPL and Pkg are just not being included into my custom sysimage? Maybe adding them to the env explicitly would make a difference?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [February 7, 2026, 9:21pm UTC](https://discourse.julialang.org/t/packagecompiler-jl-what-is-it-doing-and-how-do-i-use-it-correctly/135530/2 "2026-02-07T21:21:52Z")

</div>

Example for a script to create a system image: [KiteModels.jl/test/create\_sys\_image.jl at main · OpenSourceAWE/KiteModels.jl · GitHub](https://github.com/OpenSourceAWE/KiteModels.jl/blob/main/test/create_sys_image.jl)

One key aspect is, that you use a precompile execution file, like this:

```julia-auto
precompile_execution_file=joinpath("test", "test_for_precompile.jl")

```

It should execute a typical task of your project.

And yes, PackageCompiler is slow. For my projects it takes about 10 minutes on a fast machine with many cores. And to be able to use 8 or more cores you need 32 GB RAM. The new `juliac` compiler is faster.

A good, custom system image can speed up the FTTX a lot, for example, by a factor of three. I use a custom system image if without it the FTTX time would exceed 10s.

I put most of a project’s dependencies into a custom system image, but not the project itself. I do not put plotting libraries into a custom system image, at least not Plots.jl or PythonPlot.jl, because that can cause issues.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 8, 2026, 5:42am UTC](https://discourse.julialang.org/t/packagecompiler-jl-what-is-it-doing-and-how-do-i-use-it-correctly/135530/3 "2026-02-08T05:42:44Z")

</div>

[Technical explanation for why Package Compilier takes so long? · Issue #736 · JuliaLang/PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl/issues/736)

Not a satisfying answer and it predates the [parallelization of native code generation](https://julialang.org/blog/2023/12/julia-1.10-highlights/#parallel_native_code_generation_for_system_images_and_package_images) in 1.10, but it does mention having to build base Julia. I have no idea how to make comparisons with builds of other things mentioned there, repo size or lines of source code is only loosely correlated with compilation times, especially across different language designs.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [February 8, 2026, 5:51pm UTC](https://discourse.julialang.org/t/packagecompiler-jl-what-is-it-doing-and-how-do-i-use-it-correctly/135530/4 "2026-02-08T17:51:11Z")

</div>

Thanks @ufechner7 for the example. That matches what I think how PackageCompiler should work. However in my test I struggled to speed up the REPL experience.

Thanks @Benny for the reference. Apparently @tecosaur shares my sentiment that PackageCompiler is surprisingly slow 😅
