State of Julia: the future looks modular, generic, and fast

State of Julia 2021

July came and went, and with it JuliaCon, the annual get together of Julia users. During the three-day event, co-creators Stefan Karpinski and Jeff Bezanson once again took to the virtual stage to inform developers about the state of the programming language. Helped by Viral B. Shah, another father to the project, and Julia Computing co-founder Keno Fischer, the duo reflected upon current goings-on and gave a brief glimpse at what users can expect for the upcoming 12 months.

One of the notable developments during the last year is the number of registered Julia packages hitting 1.0 — turning almost a quarter of the ecosystem stable. Part of this seems to be down to a lot of the data analysis capabilities maturing and closing up to the mathematical packages, Karpinski found. He also noted a significant increase of speed in fundamental packages such as CSV.jl and DataFrames.jl, which maybe also put a bit of pressure on the core Julia team to keep up.

The compiler team at least, on whose behalf Jeff Bezanson presented, was quite successful in that regard. It can list faster method insertion leading to a speedup of ‘using’ statements, quicker subtyping and intersection, and fewer recompilations under recent successes. Inference improvements such as interprocedural condition propagation and constant propagation with invoke were also implemented, besides putting lots of work into CI stability to make sure everything stays current.

What’s next for the Julia compiler?

Though the number of latency PRs has almost doubled during the last year, there are still some major latency-related items on the compiler roadmap. Projects include more staging in the JIT, possibly caching code, and various algorithmic optimisations. Another area of work looks to improve the ability to build artifacts or binaries to be more specific. Currently, artifacts are basically system images, according to Jeff Bezanson, which take a long time to build and aren’t really convenient. The compiler team therefore wants to simplify and speed up the sysimg build process and increase the number of kinds of build artifacts. 

They also plan to separate the LLVM and code generation component from the Julia runtime — which should be useful for people who want to deploy smaller binaries — and add options to strip build artifacts from debug, meta and IR data to generate a more compact binary. Tree shaking and language support for separate compilation are other work items in this area, though more advanced array optimisations, garbage collection performance improvements, and compiler extensibility seem slightly more pressing to tackle.

The latter especially has been on the compiler team’s mind, because experiments for compiler optimization can mainly be found in Julia packages. Compiler APIs and other extensibility initiatives would help to support that activity properly, which is why work on initial prototyping for a compiler plugin infrastructure is under way. 

Opaque closures to hit soon

Further additions to make compiler optimisations a bit more feasible are the opaque closures that are planned to land in soon-to-be-released Julia 1.7. Before their introduction, there was no way to create a closure that always returned true, since Julia semantics would allow methods to be redefined, or capture fields in closures to be extracted, at a later stage — which alters the closure and makes its outcome tricky to predict. 

Opaque closures, however, capture the world age at creation and come with capture lists that aren’t semantically fixed — which means they can be removed by optimisers should circumstances allow. According to Fischer, opaque closures will help the compiler team build new plugins, since it lifts the restriction of having to specify closure lists and gives more flexibility at optimisation time.

During Q&A separate compilation came up, which Bezanson would like to work on in the upcoming months. If all goes well, we’ll get to see a prototype for that next year — hopefully alongside a conditional dependencies implementation, so that devs don’t have to rely on hacks in that area anymore.

Big plans for linear algebra

The roadmap for the linear algebra site of things currently sports items such as the extraction of sparse matrix capabilities from the stdlib to allow more experimentation in that regard and inclusion of Libblastrampoline. The latter is a compatibility layer that will also be part of Julia 1.7 and allows users to switch between linear algebra libraries during runtime or load multiple BLAS/LAPACK ABIs at once. 

This might be useful in the future, for various reasons. The team, for example, works on a pure Julia implementation of BLAS (or Basic Linear Algebra Subprograms) that could speed things up a lot and would be easy to test with that mechanism.

Overall, the plan is to make the linear algebra stack more flexible. “We want our linear algebra to be fully generic, fully AD compatible, run on all of the GPUs and other weird hardware that comes out, and be distributed and multithreaded and everything else“ as Viral B. Shah tried to sum up current initiatives. To make this happen, a bit of restructuring of the project might be necessary, so that not everything has to move at the pace of the standard library. But deliberations here are still in their early stages.