That’s...not really true. Ruby wasn’t really written with parallelism in mind at all, because it mostly ran on machines that couldn’t run really parallel processes. MRI threads were originally green threads, which allow a high degree of concurrency without parallelism, with less overhead than native threads.
When old MRI was replaced with YARV in 1.9 (which became the new MRI), it got native threads with a global VM lock (GVL, similar idea to Python’s GIL) which allowed running thread-safe native code with real parallelism but only having one thread running Ruby code at a time. This made Ruby thread-based concurrency somewhat more expensive, but some parallelism possible in Ruby (as native code can and some basic common processes like waiting on I/O do release the GVL.)
And Ruby 3.0 introduces a new parallelism model with Ractors (basically inspired by the Actor model), which are logically above the thread level (each contains its own set of nonshared threads) and below the process, don’t share mutable state within the VM, and each have their own VM lock, allowing a higher degree of Ruby parallelism without going multiprocess.
This is a valid summary of some facts, but not of the article or facts relevant to the article. Some quotes:
"Jekyll is not forking processes, so that is not the issue."
"The area where JRuby and TruffleRuby shine are long running processes that have had time to warm up. Based on suggestions I put together a repo of a simple small Jekyll build being built 20 times by the same process in a repo here. After 20 builds with the same running process the build times do start to converge, but even after that MRI Ruby is still fastest."
> I think there are two reasons for this:
> * Real-World projects like Jekyll involve a lot more code, and JITing that code has a high start-up cost.
> * Real-world code like Jekyll or Rails is optimized for MRI Ruby, and many of those optimizations don’t help or actively hinder the JVM.
The title seems a bit provocative, though I guess if you were reading it from within the Jekyll community, it makes sense without further disclaimers, but otherwise the article seems fairly even-handed.
The threading stuff just seems like a special case of his second point.
Commercial versions of "a JVM that can load the virtual machine, JIT and execute applications fast enough like C programs" have been available since around 2000, like Excelsior JET or WebSphere Real Time JVM among others.
The JIT cache used in recent versions of Hotspot started as part of JRockit JVM, also commercial only product.
http://www.cydiasubstrate.com/id/727f62ed-69d3-4956-86b2-bc0...
The AOT compiler only runs when the device is idle.
Starting with Android 10, they introduced a mechanism to upload PGO data into the store, so that when an APK is installed, if such data is already available the JIT/AOT don't have to relearn everything from scratch regarding the application.
https://source.android.com/devices/tech/dalvik/jit-compiler
They also improved the GC several times, the latest generation is quite good,
https://source.android.com/devices/tech/dalvik/gc-debug
There are several Google IO talks about how they went through this.
Never used it though, so no idea how it works in practice.
As it runs standalone it can also take advantage of the whole server for itself for more resource hungry optimizations without impacting running code.
The generated code is then reflected back into the client JVM instances.
But running multi-process is heavy on the JVM as it has to load the virtual machine and JIT for every process start, special when the processes are short lived.
Java solves it by encouraging running things as multi-threaded instead of multi-processed.
But Ruby wasn't built to run multi-threaded. And CRuby even if can run threads, does it by implementing a global thread lock. Aka, only one thread can run in a process at a time. The other threads have to wait until it finishes.
It looks like the multi-process implementation is good enough for CRuby and JRuby's attempt to turn it into multi threaded application didn't improve things.
Solution is to build a JVM that can load the virtual machine, JIT and execute applications fast enough like C programs.