What does HackerNews think of PackageCompiler.jl?

Compile your Julia Package

Language: Julia

Also, you can precompile a whole package and just ship the binary. We do this all of the time.


And getting things precompiled: https://sciml.ai/news/2022/09/21/compile_time/

I think by PackageManager here you mean package compiler, and yes these improvements do not need a 2.0. v1.8 included a few things to in the near future allow for building binaries without big dependencies like LLVM, and finishing this work is indeed slated for the v1.x releases. Saying "we are not doing a 2.0" is precisely saying that this is more important than things which change the user-facing language semantics.

And TTFP does need to be addressed. It's a current shortcoming of the compiler that native and LLVM code is not cached during the precompilation stages. If such code is able to precompile into binaries, then startup time would be dramatically decreased because then a lot of package code would no longer have to JIT compile. Tim Holy and Valentin Churavy gave a nice talk at JuliaCon 2022 about the current progress of making this work: https://www.youtube.com/watch?v=GnsONc9DYg0 .

This is all tied up with startup time and are all in some sense the same issue. Currently, the only way to get LLVM code cached, and thus startup time essentially eliminated, is to build it into what's called the "system image". That system image is the binary that package compiler builds (https://github.com/JuliaLang/PackageCompiler.jl). Julia then ships with a default system image that includes the standard library in order to remove the major chunk of code that "most" libraries share, which is why all of Julia Base works without JIT lag. However, that means everyone wants to have their thing, be it sparse matrices to statistics, in the standard library so that it gets the JIT-lag free build by default. This means the system image is huge, which is why PackageCompiler, which is simply a system for building binaries by appending package code to the system image, builds big binaries. What needs to happen is for packages to be able to precompile in a way that then caches LLVM and native code. Then there's no major compile time advantage to being in the system image, which will allow things to be pulled out of the system image to have a leaner Julia Base build without major drawbacks, which would then help make the system compile. That will then make it so that an LLVM and BLAS build does not have to be in every binary (which is what takes up most of the space and RAM), which would then allow Julia to much more comfortably move beyond the niche of scientific computing.

Revise.jl[1] is very helpful for development, as it allows for seamless recompilation without restarts. Cold start can also take a long time, so sometimes it helps to add options[2] such as -O0 when developing. Two paths forward for AOT compilation are PackageCompiler.jl[3] mentioned already in this thread (things like RelocatableFolders.jl[4] come in handy) and the possibility of GPUCompiler.jl[5] some day.

[1]: https://github.com/timholy/Revise.jl

[2]: https://docs.julialang.org/en/v1/manual/command-line-options...

[3]: https://github.com/JuliaLang/PackageCompiler.jl

[4]: https://github.com/JuliaPackaging/RelocatableFolders.jl

[5]: https://github.com/JuliaGPU/GPUCompiler.jl/issues/3

This is total misinformation, sorry. Julia may, depending on your setup, be slow to initially load, but the compiler is quite fast generally.

Also, there's a solution to precompile binaries with no JIT penalty...



While I definitely agree, I'd say Julia is totally fine for short scripts too. Just spin up https://github.com/dmolina/DaemonMode.jl and you can launch lots of short scripts without excessively restarting julia.

There's also PackageCompiler.jl https://github.com/JuliaLang/PackageCompiler.jl for AOT compilation, but that's heavy enough that I wouldn't bother with it for short scripts.

We call these "system images" and you can generate them with PackageCompiler [0]. Unfortunately, it's still a little cumbersome to create them, but this is something that we're improving from release to release. One possible future is where an environment can be "baked", such that when you start Julia pointing to that environment (via `--project`) it loads all the packages more or less instantaneously.

The downside is that generating system images can be quite slow, so we're still working on ways to generate them incrementally. In any case, if you're inspired to work on this kind of stuff, it's definitely something the entire community is interested in!

[0] https://github.com/JuliaLang/PackageCompiler.jl

Currently the best you can do is to build a somewhat unwieldy relocatable “bundle” with PackageCompiler.jl [1], but there are apparently plans for actual static compilation using an approach more similar to that used in GPUCompiler.jl [2], and the latter approach should as far as I understand allow for the creation of proper .so/.dlls.

[1] https://github.com/JuliaLang/PackageCompiler.jl

[2] https://github.com/JuliaGPU/GPUCompiler.jl

Makie.jl [1] does it's plotting on the GPU (like a video game engine), so can handle millions of datapoints just fine.

Also, note that for people to whom plotting is really important, it's quite easy nowadays to just AOT compile your plotting library to your sysimage with PackageCompiler.jl [2] for instant plots.

[1] https://github.com/JuliaPlots/Makie.jl

[2] https://github.com/JuliaLang/PackageCompiler.jl

Not sure about your exact use case and this is not part of Julia which I have ever used myself but the answer might be here:


There is a presentation from a recent JuliaCon by Kristoffer Carlson on the topic too, I believe.


Yeah, that's a good point. DataFrames.jl starts to really shine what the cookie cutter pandas functions arent adequate for what you need to do. DataFrames.jl can certainly be slower in some cases, but you should expect a consistent level of performance no matter what you do. This is a farcry from Pandas, which tanks by large factors when you start calling Python code vs C code.

In regards to Julia's compilation problem, you can use https://github.com/JuliaLang/PackageCompiler.jl to precompile an image, allowing you to avoid paying the JIT performance penalty over and over again.


Note that it doesn't do slim binaries yet for embedded. Don't know if that's in the roadmap.

There will be more caching in the future, but until then it sounds like you'd like PackageCompiler.jl (https://github.com/JuliaLang/PackageCompiler.jl) to build DiffEq and Plots into your sysimage.
I don't think this is a great reason to avoid julia.

Why is latency a concern for you? Are you running a lot of short, one-off scripts? If so, an easy solution is to just keep a julia session running and re-use it for each each script rather than constantly starting up and closing julia sessions. DaemonMode.jl [1] is a package that was recently developed that makes this workflow effortless.

Another option if you've got some production code that needs to be run over and over again is to create a custom sysimage with everything AOT compiler. PackageCompiler.jl [2] makes this workflow pretty easy nowadays.

[1] https://github.com/dmolina/DaemonMode.jl

[2] https://github.com/JuliaLang/PackageCompiler.jl

Yes, with PackageCompiler.jl. There are some restrictions IIRC since it is a dynamically typed language.


Look under Static Julia Compiler here [1]. I've successfully done it in Linux, don't know about Windows. It doesn't work when you have binary dependencies like GTK, etc.

[1] https://github.com/JuliaLang/PackageCompiler.jl

There are some docs here: https://docs.julialang.org/en/v1/devdocs/sysimg/index.html

There is also now PackageCompiler that provides a nicer API without requiring you to build from source: https://github.com/JuliaLang/PackageCompiler.jl

I think this [1] is the latest on static compilation -- they're working on it

[1] https://github.com/JuliaLang/PackageCompiler.jl

Lots of the complaints in the article seem a bit contrived or not too relevant. To mention a few:

Performance: It's been mentioned by others that JIT and Julia is a thing. An important point that many here seem to be unaware of is that you can compile your Julia code [0], and then end up with a fast Hello World, if that kind of thing floats your boat.

Language style: This is more or less a subjective thing, right? However, I've found that optimising for JIT forces me into writing short and pure functions. I.e., optimising my Julia code for speed also forces me to write clean code. This is a really nice byproduct of the language design.

Libraries: The complaints seem somewhat thin: there is no mention of the type of unit tests that the author is missing, just a complaint that the library is less featured than some in C++ or Java. Is comparing a pre-1.0 language's unit testing libraries to those of C++ and Java a fair thing anyway? Finding that the generated instructions of a print statement are too long for your liking also does not seem to me to be a fair criticism of the language libraries.

Development: Complaining about the codebase being a mishmash seems unfair to me as well. I find myself browsing source code in Julia much more than other languages. With Julia I can just dive in and generally find that what's relevant to me underneath is also Julia.

[0] https://github.com/JuliaLang/PackageCompiler.jl

> like piping CLI commands together, in Julia's case you're looking at pathetic 3 execs per second.

If you want to build CLIs without the JIT overhead, you can compile your Julia code: https://github.com/JuliaLang/PackageCompiler.jl

JIT overhead/startup time is still comparably large. There is https://github.com/JuliaLang/PackageCompiler.jl that helps reduce this overhead in user libraries. The base library precompiles quite a few methods already, so the performance deficit relative to C and Python on Julia 1.2 is half that quoted in the article, and unchanged by statically compiling.

Personally, I do a lot of computational geometry in Julia and I really don't care so much about these kinds of small overheads since actual computation time is the dominant factor. I imagine if Julia was designed for scripting in Unix environments this would be a bigger deal, but I think most people in the Julia community care more about how to manage several gigabytes of data in RAM/cache and run some analysis quickly, e.g. composable multithreading in 1.3.

The "time-to-first-plot" (compiler latency) problem is something that the Julia gurus know about and are working on. For example, Jeff Bezanson gave a talk [1] at the just-completed JuliaCon that listed this as the first on a list of known problems with Julia.

One immediate solution is to use PackageCompiler.jl [2] to build a Julia image that includes a pre-compiled version of the slow code (packages).

[1] https://www.youtube.com/watch?v=TPuJsgyu87U&t=11s

[2] https://github.com/JuliaLang/PackageCompiler.jl

There's PackageCompiler[0] which allows to precompile the packages you need for work into a system image. This means avoiding precompilation in the REPL every time you start up Julia. That's if you start with the custom system image.

However, it's a community effort and is somewhat non-trivial to get up and running with. Once Julia gets better precompilation/binary packaging support, common workflows like plotting will improve dramatically.

[0]: https://github.com/JuliaLang/PackageCompiler.jl

- Doesn't compile to native code (there are ways to do it, but too complicated and there are caveats).

What do you mean by that? It absolutely is compiled to e.g. x86_64 instructions by default, going through LLVM. Do you mean no standalone binaries? If so, that's actively being worked on by e.g. PackageCompiler.


Julia is a general-purpose programming language. The language itself is actually really good as a scripting language, including integrating well with shell, C, Fortran, R and Python, for example:


The only trade-off here is the restricted resources the Julia devs can afford. Focusing on the scientific computation niche, the Julia compiler was built to compile code just ahead of time, since this way it can create code as fast as compiled languages while still being dynamic like any interpreted language (such as Matlab and Python). But there is nothing in the language that prevents it from being fully interpreted (and therefore having minimal compile time overhead, but generating poorly optimized code for long running processes), or alternatively pre-compiling and caching to have both (which is being worked on: https://github.com/JuliaLang/PackageCompiler.jl )

Unfortunately, not really. There is some community work in that regard [1], but it doesn't seem to get as much attention as one would like. Some people have gotten it to work, but official support (guaranteeing maintenance and decent documentation) for static compilation and easy deployment would make a huge difference.

[1] https://github.com/JuliaLang/PackageCompiler.jl

>I would want a convenient way to deliver a self-contained executable.

It's a bit rough around the edges, but it does exist: https://github.com/JuliaLang/PackageCompiler.jl

Like Stefan said, static compilation has been possible for years, just not very user friendly. We've been working on making compilation easier here: https://github.com/JuliaLang/PackageCompiler.jl

And we have a package for building complete, standalone, desktop applications out of the compiled code, here: https://github.com/NHDaly/ApplicationBuilder.jl

> does this involve bundling all of Julia w/llvm and all?

Yeah, more or less. It involves bundling the julia runtime shared library (no different than a C++ program needs access to the C++ runtime library, except that usually comes pre-installed), and all its dependencies, which yes, includes llvm and all.

A far-off goal is to be able to shave off the pieces of the runtime you don't need, such as LLVM if everything is precompiled, FFTW if your program isn't doing heavy linear algebra, etc.

As far as I know, Julia only allows for dynamic libraries.


Which really for me they are good enough, I don't remember the last time I cared about producing a .a/.lib file for delivery.