Misc #18968


Run MJIT under a forked Ruby process

Added by k0kubun (Takashi Kokubun) almost 2 years ago. Updated almost 2 years ago.




  • When MJIT compiles a method, it spawns a child Ruby process and lets it generate a C code and compile it.
  • Stop supporting platforms without fork(2), i.e. mswin
    • A suggested alternative to it in Windows, in general, is running the implementation for Linux on WSL. It's likely already faster than the mswin one because of recent SIGCHLD-related changes.


To improve the maintainability of MJIT's optimization logic, I'm planning to rewrite MJIT in Ruby.

To run Ruby code safely, you need a GVL or at least be on a Ractor. Doing so in the main thread would cause performance problems. We evaluated running MJIT on a Ractor, but enabling the multi-Ractor mode slows down things.

The proposed change, forking a child process, doesn't enable the multi-Ractor mode, and it's confirmed to be faster than the Ractor-based patch. If you fork a process and run it for a while, you need inter-process communication to give the latest inline cache contents. But it requires synchronization. Another option that doesn't require synchronization that much is to fork a process every time, which is what's discussed in this ticket.

Actions #1

Updated by k0kubun (Takashi Kokubun) almost 2 years ago

  • Description updated (diff)

Updated by chrisseaton (Chris Seaton) almost 2 years ago

An interesting project if you are changing the interface could be to write a generic JIT interface, which any JIT could plug into. At the moment we have custom C code to plug in MJIT and YJIT - an interface could reduce that C code and enable more experimentation with JITs.

In Java, this is called JVMCI - the JVM Compiler Interface.

Updated by k0kubun (Takashi Kokubun) almost 2 years ago

Yeah. Ever since I created llrb.gem, I've sometimes thought about it. Like what the description of JEP 243 says, JIT needs to know about VM data structures, which are currently just part of C code in vm.c. If we provide that and make jit_exec pluggable, that'd be the minimum common requirement for CRuby JITs. Chances are I might end up achieving it this time by making MJIT written in Ruby because everything will be dynamically accessible and monkey-patchable.

Actions #4

Updated by k0kubun (Takashi Kokubun) almost 2 years ago

  • Status changed from Open to Closed

Applied in changeset git|dc8d70e4615cdf12378322fbcd4396486270ddbe.

Execute MJIT in a forked Ruby process (#6264)

[Misc #18968]


Also available in: Atom PDF