Julia's GC vs. Go's GC (and more). Good idea to compile Julia to Go?

From the interesting keynote from the International Symposium on Memory Management (ISMM) on June 18, 2018:

Again we kept knocking off these O(heap size) stop the world processes. We are talking about an 18Gbyte heap here. We had much larger heaps and as we knocked off these O(heap size) stop the world pauses, the size of the heap could obviously grow considerable without impacting latency. So this was a bit of a help in 1.7.
[…]
That dropped us into the sub-millisecond range. Again the Y axis is about to change to 1.5 milliseconds and we see our third order of magnitude improvement.
[…]
We know what is causing the remaining pauses. The SLO whisper number here is around 100-200 microseconds and we will push towards that. If you see anything over a couple hundred microseconds then we really want to talk to you and figure out whether it fits into the stuff we know about or whether it is something new we haven’t looked into. In any case there seems to be little call for lower latency. It is important to note these latency levels can happen for a wide variety of non-GC reasons and as the saying goes “You don’t have to be faster than the bear, you just have to be faster than the guy next to you.”

There was no substantial change in the Feb’18 1.10 release just some clean-up and chasing corner cases.
[…]
We now have an objective of 500 microseconds stop the world pause per GC cycle. Perhaps a little sandbagging here.
[…]
Again this is not an SLA but an SLO so it’s an objective, not an agreement, since we can’t control such things as the OS.
[…]
P.S. The Go team is looking to hire engineers to help develop and maintain the Go runtime and compiler toolchain.

A. Now, I really like what mainly our one Julia guy has done regarding Julia’s GC. I don’t have any numbers, is Julia’s GC still competitive?

I know you can call Go (or from Go). I believe as with calling Java, then you have two runtimes and both with their own GC. While I don’t like Go as a language, I do like what their GC work (and some more). Does it make sense to compile Julia to Go?

We already have work for static compilation, with compiling to Go you get that for free (and they already have “gomobile build” that compiles the same Go codebase to either Android (generates APK) or iOS. I would like Julia to target both (at least Android) somehow.

B. They also do good work with concurrency, while not with race condition safety (then e.g. Rust is better). I believe neither does Julia have such safety… Would Julia’s code map well to their infrastructure? They have e.g. many stacks (thousands), is this a problem? I believe we have better FFI, but we could map to theirs and take a small speed penalty?

They also can now compile to WebAssembly.

1 Like

I possibly don’t understand the context here very well, but let me take a stab at answering your question.

I think there are many features of Julia that wouldn’t map to Go very well. Whilst you could write a Julia compiler in Go, this is different to having Julia programs converted to equivalent Go code. The latter would probably incur a much larger performance penalty than what you are trying to save.

I believe that your question depends a lot on your application. If your application requires much lower pause times that Julia can provide, it may make sense to either work on an optional replacement for the Julia GC that does what you want, or to write in Go or some other language for that component of your project, and stick to Julia for the parts that don’t have that requirement.

3 Likes

I would start with collecting these numbers for some frequent use cases in both languages. I’m pretty much sure for many tasks that Julia was designed for it will beat Go e.g. by not producing garbage at all. Without concrete examples and measurements discussion of the features isn’t very useful.

1 Like

Right, i.e. linear algebra; 2D+ array-oriented (of bittypes, no pointers) code may not exercise the GC much. And some code not at all (what you want for hard-real-time).

I remember reading, even with the huge success for the Celese.jl projects, that there where some loose ends with the GC (nothing I’m too worried about, I expect you can do [small] improvements and there are no show-stoppers for HPC, and with the results already excellent).

I’m not saying it makes sense for all Julia users to compile to Go (or Java), and while you might gain with its GC (its low latency/predictability), you might lose in overall speed. I just see it as a potential option for some applications. E.g. for hard-real-time you either want a language with no GC, or where you can avoid GC/dynamic allocations entirely (e.g. in Julia, D, Nim), but in some codes, i.e. for (soft-real-time) 3D games, I could see you could avoid it for most of the code, but maybe not all of your code (code base could be huge).

It only takes one of your functions to allocate, and then eventually you much do GC and “stop the world”.

Java has a zoo of GC algorithms (and more and more coming), including real-time options (“Metronome”). Go likes to keep things simple with just one, and one tunable option (and now one more, or at least soon).

Even if it may “make sense to either work on an optional replacement for the Julia GC that does what you want” and you could copy e.g. Go’s design, I’m just not sure we can keep up with Google’s engineers plus with them “looking to hire engineers”. This is a very high-level goal for them (and they’ve succeeded already it seems), but a low-priority for Julia?

While linked-lists should be avoided at all costs (and are not provided in Julia’s standard-library), you may sometimes want them (or a variant of) as an exception, or other pointer structure, i.e. all kinds of trees. [Light]Graphs.jl is also a potential Julia application, and I believe a state-of-the art library.

From one of my favorite Julia case studies, it’s already appropriate for hard-real-time, and i.e. more appropriate than Java (or even C++):

https://juliacomputing.com/case-studies/mit-robotics.html

If you’re writing a controller for a walking robot and it doesn’t provide new motor commands at a near-constant rate, the robot may literally fall over. This typically means avoiding dynamic memory allocation as best as possible, as memory allocation algorithms themselves typically don’t have hard real time guarantees. In languages like Java and Julia, the garbage collector is an additional source of jitter. The garbage collector typically ‘stops the world’ for up to several milliseconds while it does its job, possibly resulting in a robot lying on the floor.
[…]
we find Julia to be more productive than Java. First, Julia provides immutable, stack-allocated user data types, while Java (at least as of now) only stack-allocates predefined primitive types like integers and doubles (note that sometimes Java can avoid dynamic allocation of non-primitive types as an optimization, but that’s not guaranteed). In contrast, in Julia you can simply create, for example, a fixed-size 6-vector (provided by the wonderful StaticArrays package, which provides functionality and performance similar to the fixed-size matrices from the Eigen C++ library) in a function and return it by value, while the (tedious) pattern in Java is to pre-allocate everything and have methods mutate their inputs in place. Second, JIT compilation is also better than in Java.

GitHub - JuliaCollections/DataStructures.jl: Julia implementation of Data structures with “unrolled linked list”