|
|
Subscribe / Log in / New account

New horizons for Julia

January 31, 2025

This article was contributed by Lee Phillips

Julia, a free, general-purpose programming language aimed at science, engineering, and related arenas of technical computing, has steadily improved and widened its scope of application since its initial public release in 2012. As part of its 1.11 release from late 2024, Julia made several inroads into areas outside of its traditional focus, provided its users with advances in tooling, and has seen several improvements in performance and programmer convenience. These recent developments in and around Julia go a long way to answer several longstanding complaints from both new and experienced users. We last looked in on the language one year ago, for its previous major release, Julia 1.10.

Static binaries

It's simple to share Julia projects in environments where Julia is already installed: provide the text files containing the program and one additional text file, called Project.toml, which lists the direct dependencies of the code. This latter file is generated automatically by Julia. The recipient need merely execute the single command instantiate to have Julia install any needed packages to exactly reproduce the environment.

This works well with colleagues who happen to be Julia users; it is great for collaborative development and for reproducibility in scientific research. However, it's a dead end for colleagues who do not have Julia installed. Distributing the program in the form of an "app" would solve the problem, but a normal installation of Julia provides no obvious way to do this.

As Julia is a compiled language, one might wonder what the problem is. After all, you can compile your Fortran or C program into a compact, self-contained (perhaps, depending on shared libraries) binary, and even target a variety of architectures with cross-compilation. Anyone can run these binaries, without a compiler installed.

It has also been possible to compile a Julia program into a static binary for some time, using the PackageCompiler package. Experienced Julia hands use this package to create "system images" (or "sysimages") that contain the Julia runtime along with frozen versions of packages used in their projects. These sysimages load instantly and save time when one is not currently using the Julia read-eval-print loop (REPL).

The major improvements in precompilation and package-loading times that came with 1.10 largely obsoleted the use of PackageCompiler to save startup time. PackageCompiler might still be a solution to the problem of binary distribution except for one serious issue: the binaries that it generates are huge.

The sysimages created by PackageCompiler contain the Julia runtime, the entire standard library, parts of the LLVM compiler, and more. The result is that a "hello, world" program is burdened with about 150MB of stuff that it does not use. (The compiled "hello, world" program will, for example, contain the BLAS linear algebra routines, because, in its current state of development, PackageCompiler does not figure out that they are not needed.) This is a vast improvement over earlier incarnations of PackageCompiler, which turned "hello world" into a gargantuan 900MB, but does not compare well with, for example, the Fortran equivalent. I just used the gfortran compiler to process a Fortran 90 "hello world" program and found that it resulted in a tiny 17KB binary.

Efforts toward reducing the size of binaries have also involved another package for static compilation. This package is only useful for relatively small Julia programs, however, and is confined to a severely limited set of language features. Within these limitations, StaticCompiler can produce truly small binaries, similar in size to those produced by C and Fortran. Because of the limitations, however, interest remained focused on the evolution of PackageCompiler.

Why can't PackageCompiler just strip out the unneeded stuff and create binaries of a reasonable size? That's the obvious question, but finding a way to eliminate the unneeded baggage turned out to be a difficult problem. Julia's dynamic design and its focus on REPL-driven development mean that its runtime and "just-ahead-of-time" compiler were envisioned to be always available behind the scenes. They are used to compile new methods for newly-encountered mixtures of argument types and to keep the whole array of language features at the ready, including various types of introspection. This is the essential reason that binaries created by PackageCompiler are so large, and why so much work was required to allow the programmer nearly full use of all language features while not dragging the entire runtime along with each compilation target.

The goal of creating small binaries has occupied a handful of talented developers over the past few years, and they have recently achieved a new level of success. Development builds of Julia now include an experimental method of invoking the compiler called juliac. This compiler invocation script comes with a --trim flag that "trims" away whatever is not needed to run the program, while still allowing the use of nearly all normal Julia features. The idea is that the user will be able to type juliac at the terminal, instead of julia, to compile a binary rather than run a program or start the REPL. The result is an impressive 90% reduction in final binary size compared with the current version of PackageCompiler. The exact size of "hello world" is fluctuating some in the development builds as of this writing, but it is around 900KB.

The next major Julia release, 1.12, is likely to appear in mid-2025. It will finally include the ability to generate static binaries of a reasonable size, appropriate for distribution. This will be a refinement of the juliac mechanism that is already merged into the development branch.

Static compilation will be the definitive answer to the complaints and wishes of many Julia programmers who have wanted their favorite language to be able to do what the traditional workhorses for scientific computing have done for decades.

juliaup

Julia has always been easy to install and upgrade on operating systems such as Linux and BSD: simply download and expand the tarball and place a link to the julia binary in your path. Julia's package system also makes it easy to keep any number of Julia versions installed on the same machine, with dependencies correctly resolved for projects using different versions of the language. However, it's clear from questions on forums that there are many users of Julia who are less comfortable using command-line tools to navigate their filesystems. Installing, upgrading, or switching among versions often leads to confusion.

Now there is a utility called "juliaup" to make their lives simpler. As juliaup has become the recommended way to install and upgrade Julia, it's now widely used even by Linux adopters (although I am set in my ways and don't bother with it). juliaup does provide some useful abstractions. These are built around its concept of "channels". Some examples of juliaup channels are release, referring to the latest stable version of Julia; lts, referring to the "long term support" release; beta, pointing to the most recent beta; and nightly, pointing to, perhaps unsurprisingly, the nightly build. Thanks to this channel abstraction, one need never refer to Julia's version numbers.

To get the latest nightly, a user simply types:

    $ juliaup update nightly

juliaup also provides a new, flexible julia command for starting the language. To run the nightly build, the command is:

    $ julia +nightly

After executing the command:

    $ juliaup default release

the plain julia command will now use the stable release.

These are just a few examples of how juliaup works. It comes with a collection of other commands to do such things as list available channels, update all channels at once, or refer to specific Julia versions, as well.

Julia in web browsers

These days, fairly complex simulations written in Julia can run completely within the web browser. Alexander Barth has created a fun and addictive simulation of fluid flow that runs in the browser. The visitor can draw boundaries with the mouse and watch the pressure field adapt. The same author has also created a browser-based simulation of surface waves. Those with an interest in chaos theory can find an in-browser solution of the famous Lorenz system of ordinary differential equations. It's remarkably fast, and the demonstration comes with a tutorial explaining how it was done.

These three examples were written not in JavaScript, but in Julia, and run in the browser thanks to WebAssembly. Launched in 2015, WebAssembly (often abbreviated "Wasm") is a binary instruction format that has become widely deployed in modern web browsers. It potentially allows any language to run in a browser, provided someone has written a WebAssembly compiler for it.

The growing list of source languages with WebAssembly compilers in various stages of development is encouraging. We can already use Python, C, Go, Lua, Rust, and many others as replacements for JavaScript. However, despite the impressive examples above, Julia for WebAssembly is still in the early stages of development. Only a restricted subset of the language is supported (for example, no multidimensional arrays). However, the problems encountered in creating small binaries have some overlap with the problems of targeting WebAssembly, so recent progress in the former is likely to help speed along the latter.

Readers interested in getting their Julia programs running in the browser should start with the WebAssemblyCompiler package. The author warns that the code is experimental, but it comes with guided examples.

Features of 1.11

The latest release of Julia is 1.11.3, unveiled on January 21, 2025. The release notes for the 1.11 major version, which appeared on October 8, provide detailed information on the improvements to the language in that release. Here I'll summarize some of the most important and interesting language developments since 1.10.

MemoryRef datatype: many array operations had been implemented in C up to now, which created some overhead. These have now been moved to Julia code thanks to a new datatype called MemoryRef. The performance improvements coming from this change include a doubling in speed of the push!() function that inserts items onto the end of an array. The maintainer of the WebAssembly package remarked that the MemoryRef datatype will finally allow multidimensional arrays to be used in Julia programs destined for WebAssembly.

public keyword: as pointed out in our article about Julia's package system, names in a module can be explicitly exported, which allows their use without namespacing. For example, Base is a library that is automatically imported into every Julia environment. It provides hundreds of functions, from basic mathematical workhorses such as sin() to string manipulation routines such as split(). Julia programmers can use these functions by invoking their unadorned names because they are exported by the modules in which they are defined.

However, Base also contains functions useful in more unusual contexts that are not exported. One example is Base.OneTo(n), which returns something like the interval 1:n, but slightly different in the way that it's treated by the type system. Those who know that they need this function must namespace it by prefixing Base. Although not exported, Base.OneTo() is "safe" to use; it's intended for public consumption and will not break future code. This is not the case for every unexported function defined in every module. Up to now, there was no standard way to tell the difference between a safe unexported function and one that should be considered "private", in the sense that it may not be future-proof. Now Julia's public keyword fills this gap by marking names that are safe to use even if they are not exported. Of course Julia will not stop programmers from using names not so blessed, but now it will warn them.

stdlib excision: Julia 1.11 continues the process that has been underway for a couple of years to remove modules from the standard library and turn them into normal packages. This allows them to be developed independently from releases of the language, which generally allows a faster pace of improvements. It also allows Julia to be distributed with a smaller sysimage, purged of unnecessary libraries, that can start faster and consume less memory. In the latest release, modules from stdlib will all have their own version numbers, formalizing their independent existence.

@main: Julia 1.11 added a @main macro that marks which function in a Julia program file will be the entry point when the program is run (rather than imported). This lets programmers use the same file as a resource imported into other programs and as a file to be executed. For example, a module that consists of a list of function definitions can be imported into another program without any side effects. But if one of those functions is decorated with @main, then, if the same file is executed (for instance by typing "julia file.jl"), in addition to the functions being defined, the one so marked will be run. This is semantically identical to inserting a line at the bottom of the file invoking the name of the main function; thanks to @main, one version of the file can now be used both ways.

Conclusion

Due to the accumulation of improvements in the last several versions of Julia, startup times have become fast enough that I have begun to use the language for utility scripting, something that would have been impractical a few years ago. This trend continues in the most recent version, and the greater ease of compiling programs promised in the next version should make Julia even more suited for building system utilities. It's already become a serious contender to replace Bash and Python for my purposes. If WebAssembly targeting continues to make progress, which the improvements to compilation will also contribute to, then Julia will become a welcome replacement for (or addition to) JavaScript as well, further extending its scope of application.

A solution to the problem of small binaries, to be released as part of 1.12, should allay the misgivings of those for whom the difficulty of sharing compiled programs has kept them away from the language. For Julia's core original audience, who were accustomed to amortizing large compilation times over simulation times measured in days or weeks, the new language's awkwardness in some interactive contexts was an acceptable tradeoff to finally have a modern, expressive medium that did not entail compromises in performance. By successfully meeting the objections of Julia's critics in several key areas, its developers have ensured that their language is poised to widen its scope far beyond that original core user base.


Index entries for this article
GuestArticlesPhillips, Lee


to post comments

+1 for this article...

Posted Jan 31, 2025 17:20 UTC (Fri) by rsidd (subscriber, #2582) [Link]

and for the static compilation and webassembly features in particular. I already use Julia quite a bit, and maybe these will get others interested too.

Distributions

Posted Feb 3, 2025 8:25 UTC (Mon) by stephanlachnit (subscriber, #151361) [Link] (18 responses)

As long as they fail to manage to get Julia into all major distributions, I fail to see how it can gain traction as a replament for Bash / Python scripts. But they don't really seem into understanding how distros work or why they should care.

Distributions

Posted Feb 3, 2025 14:45 UTC (Mon) by leephillips (subscriber, #100450) [Link] (17 responses)

Julia is available through the package managers of all major Linux distributions, but, as warned on the official Julia download page, you shouldn’t use these packages. Such packages are typically put together by people involved with the distributions, not the developers of the packaged software. In the case of Julia, some distributions package broken Julia installations, some are simply out of date, and some are fine. I use Debian; most packages for actively developed, end-user software are very out of date, and Julia is no exception. I use the Debian package manager for utilities such as Bash and for shared libraries, etc. For mutt, zsh, Google Chrome, Postgres, and almost everything else that I interact with directly, the package manager is useless and I download the software from the developers’ sites, either in binary or source form. This is normal.

Fedora, for another example, happens to package an up-to-date Julia.

If the Julia site instructed people to use their distributions’ package managers the Julia devs and community would spend an inordinate amount of time fielding bug reports and questions that have nothing to do with Julia but arise from the broken nature of these packages. They could devote themselves to working with each distribution to help them package a timely, non-broken Julia for each new release, but I, personally, would much rather that the massive amount of developer time that this would consume be dedicated instead to developing Julia.

See https://github.com/JuliaLang/julia/issues/32639#issuecomm... for further detailed explanation of why depending on distribution packaging for Julia would present a host of problems.

Distributions

Posted Feb 3, 2025 15:17 UTC (Mon) by intelfx (subscriber, #130118) [Link] (9 responses)

> but, as warned on the official Julia download page, you shouldn’t use these packages

Any free software project that posts this kind of "warnings" earns my immediate distrust, and it would take *a lot* to offset it.

> Such packages are typically put together by people involved with the distributions, not the developers of the packaged software.

And that's how it should be.

Distributions

Posted Feb 3, 2025 15:41 UTC (Mon) by Wol (subscriber, #4433) [Link] (1 responses)

> > Such packages are typically put together by people involved with the distributions, not the developers of the packaged software.

> And that's how it should be.

And that's how it SHOULDN'T be. Would you want your car serviced at the local garage by an unsupervised apprentice?

IF (unlikely) I ever get any software of mine into a mainstream distro, I would consider it very important that I provide up-to-date build options for any distributions of importance to me. Probably Gentoo, SUSE, Slackware. I would expect any collaborators to do the same for distributions of importance to them.

Expecting people who aren't involved with the software (*especially* if it's under active and rapid development) to package it is just asking for something to go wrong.

Cheers,
Wol

Distributions

Posted Feb 3, 2025 17:26 UTC (Mon) by jond (subscriber, #37669) [Link]

And that's how it SHOULDN'T be. Would you want your car serviced at the local garage by an unsupervised apprentice?
I don’t like this analogy because it presumes there is only one field of expertise that matters. I fully accept that the developers of a program are the experts in that domain; but packaging itself (and distribution specific facets) are another relevant domain entirely, which upstream developers rarely are expert in. I agree there’s a problem here. But the way you’ve presented it I think misses important nuances.

Distributions

Posted Feb 3, 2025 16:00 UTC (Mon) by leephillips (subscriber, #100450) [Link] (6 responses)

“Any free software project that posts this kind of "warnings" earns my immediate distrust”


But this sort of thing is extremely common, because packages from distributions are so often useless.

Just looking at some of the free software I use every day:

The Mutt (the email client I use) official wiki instructs users to install by downloading the source from mutt.org and compiling.

Dwm (the window manager I use) tells users to download source and install, pointing out that it would be “pointless” to distribute binary packages.

Pandoc recommends downloading from pandoc.org to get a recent version.

LaTeX: they mention that distribution packages are typically out of date and direct users to download from the project.

Distributions

Posted Feb 3, 2025 16:22 UTC (Mon) by Wol (subscriber, #4433) [Link]

Okay, this story is many years old (I don't know how long I've been using gentoo, but it's a LOT of years), the reason I switched to gentoo was because I was running the latest SUSE, the latest distro version of lilypond, and for whatever reason I needed a much newer version of lilypond.

Cheers,
Wol

Distributions

Posted Feb 3, 2025 17:29 UTC (Mon) by jond (subscriber, #37669) [Link] (2 responses)

But this sort of thing is extremely common, because packages from distributions are so often useless.
This framing is disingenuous. The mutt package, to pick your example, is obviously not useless; it’s widely used by many people. I used it myself for at least 20 years. I’m sure that you’re right, the upstream maintainer would prefer I used a more recent release, but that’s a different matter from the older version being useless.

Distributions

Posted Feb 3, 2025 17:43 UTC (Mon) by leephillips (subscriber, #100450) [Link] (1 responses)

I admit that an out-of-date package might not be useless, and in fact I use some of them where it doesn’t matter to me whether I have a recent release. But my statement is still true, that “packages from distributions are so often useless”.

Distributions

Posted Feb 3, 2025 18:14 UTC (Mon) by jzb (editor, #7867) [Link]

I'm not sure useless is a, well, useful term here. Perhaps what you mean to say is that packages from the distribution are older than you or other users would prefer, or that they may be altered in some way that is less optimal for some or many users—for example, those who depend on / want a vanilla upstream version/experience.

If that is what's meant, I don't think that's controversial at all. I am quite happy to get the bulk of my software from my distribution of choice, but I do compile certain things (e.g., aerc) from source because I want the very, very latest as it's still pretty new and fixes and features land regularly. OTOH, I am not going to bother to compile VLC, Foliate, Pandoc, or ffmpeg myself unless there's a really good reason.

Distributions

Posted Feb 3, 2025 17:35 UTC (Mon) by ballombe (subscriber, #9523) [Link]

This is different.
They tell you how to get the latest version, they do not tell you that you should not use distro version.
(it should be noted that lot of linux users are running very old LTS release like Ubuntu 18.04 which can be annoying to upstream, but it is not the distributions fault).

Mutt
"Figure out if you have a mutt installed already by entering "mutt -v" at the prompt. If you have none yet, or the displayed configuration doesn't suit your needs, grab the source from http://www.mutt.org/download.html and "do it yourself": install mutt."

DWN
"Because dwm is customized through editing its source code, it's pointless to make binary packages of it. This keeps its userbase small and elitist. No novices asking stupid questions. There are some distributions that provide binary packages though."

PANDOC
"Check whether the pandoc version in your package manager is not outdated. Pandoc is in the Debian, Ubuntu, Slackware, Arch, Fedora, NixOS, openSUSE, gentoo and Void repositories."

LaTex
"Check your Linux distributions software source for a TeX distribution including LaTeX. You can also install the current TeX Live distribution directly---in fact this may be advisable as many Linux distributions only contain older versions of TeX Live, see Linux TeX Live package status for details."

Distributions

Posted Feb 13, 2025 8:55 UTC (Thu) by anton (subscriber, #25547) [Link]

I use mutt, pandoc, and latex from Debian oldstable, and I find them useful. Of course they do not offer newer features, but that does not make the old versions useless. If you think that the current upstream version of mutt, pandoc, and latex are useful, why would they become useless in the future?

OTOH, the Debian package maims gforth by deleting the manual (they do not put it into non-free or something, they just do not distribute it at all). This makes Debian's Gforth distribution mostly useless without internet access; ok, not completely useless: It still can be used for building upstream Gforth from git (but there are frequent snapshot tarballs of upstream Gforth, so that benefit is small).

Distributions

Posted Feb 3, 2025 21:39 UTC (Mon) by wjb (subscriber, #71810) [Link] (3 responses)

I've been trying Julia recently and thought I'd try building it from scratch, then started to wonder how that worked and fell in a rabbit hole.

It's got a hellish build, or if I'm being kind, "fragile". All done with make, the makefile's all follow a pattern (which is good I suppose), but they are hard to follow (yes I know that's my problem) and the header->object dependencies are detailed & explicit (which makes me think they're generated, there's no actual sign of that but I'd hate to think they're maintained manually). Also lots of bundled/patched/forked dependencies, which makes me uncomfortable because "why?".

Distributions

Posted Feb 3, 2025 23:40 UTC (Mon) by leephillips (subscriber, #100450) [Link] (2 responses)

You are brave. I’ve never tried compiling Julia from source.

An explanation for at least some of the patched dependencies (mentioned in the Github issue I linked in a previous comment) is the circumstance that the Julia project uses patched versions of several libraries, most notably LLVM itself, to which it has contributed many improvements and fixes.

Distributions

Posted Feb 4, 2025 18:29 UTC (Tue) by ballombe (subscriber, #9523) [Link] (1 responses)

So you neither use distribution binaries nor compile them from source ?
What are you advising to do then ?

Distributions

Posted Feb 4, 2025 19:01 UTC (Tue) by leephillips (subscriber, #100450) [Link]

To install Julia, go to https://julialang.org/, click on the big green Download button, and follow the instructions.

Distributions

Posted Feb 5, 2025 19:48 UTC (Wed) by stephanlachnit (subscriber, #151361) [Link]

I agree that for some software, package managers are not the best way to get it anymore. Like GUIs (use flatpak) Rust crates (use cargo) or even most Python packages (use pip).

But this is not true for the core languages. It would be horrible for user friendlyness if GCC or Python itself are not available in most distributions. It is already not ideal for Rust.

Sure, developers can and will use more upstream compiler / interpreter version, but if you get started or just want to compile / use software X, this should not be a requirement. This is where Julia fails.

I can even understand, that they complain about broke distro builds. But it is an entirely self-made problem: Julia's developer don't understand or don't want to understand how distros work, why their build system and bundling is horrible, and how that leads to broken builds. Almost every other relevant langauges manages to get the core language components in all major distros. Most even care about it. Except Julia.

Distributions

Posted Feb 6, 2025 10:59 UTC (Thu) by aragilar (subscriber, #122569) [Link]

It been out of Debian-based distros for a few years now.

Distributions

Posted Feb 27, 2025 18:13 UTC (Thu) by zimoun (guest, #136589) [Link]

Hum, I would like to mitigate a bit. :-)

First, I find surprising that on one hand, LWN covers Reproducible Builds and Supply Chain attack and on the other hand, kind of promote an anti-pattern as `juliaup`. Somehow, that's because downstream distribution and third-party are not able to fully audit that some supply chain attacks pop up here or here, IMHO.

Second, as one packager of Julia for Guix, the pin-pointed message #32639 does not appear fully accurate. The issue is not about their own Julia patched libraries -- in Guix, we include them as `llvm-julia` or `libuv-julia` etc. -- the real issue is that Julia upstream does not really care about downstream distribution. Somehow, Julia upstream (kind of) promotes: our binaries or nothing -- as you wrote :-) --; so see first point above. ;-)

That's said, Julia is a great programming language. And I always enjoy LWN's cover of Julia, very good job. Thank you!

I prefer Python for GUI work.

Posted Feb 3, 2025 20:40 UTC (Mon) by ccchips (subscriber, #3222) [Link]

I always like to try and get Tk working when I try a computer language. The Tk that has been built for Julia is not working as I would epect, and I don't see much interest in fixing it. Python is still my favorite language for GUI programming in a scripted environment.

There are visualization tools for Julia, but I haven't got to them yet.

Julia for embedded and realtime applications

Posted Feb 6, 2025 21:16 UTC (Thu) by leephillips (subscriber, #100450) [Link]

This appeared a few days ago on the arXiv:

“C-code generation considered unnecessary: go directly to binary, do not pass C. Compilation of Julia code for deployment in model-based engineering”

It’s all about using the juliac compilation script described in this article to create small, fast binaries suitable for embedded and realtime deployments.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds