6 ms·
> Unlike ordinary JIT compilers for other languages, Ruby’s JIT compiler does JIT compilation in a unique way, which prints C code to a disk and spawns common C
by blattimwind 8y ago
> Unlike ordinary JIT compilers for other languages, Ruby’s JIT compiler does JIT compilation in a unique way, which prints C code to a disk and spawns common C compiler process to generate native cod e.
Oh dear god.
- pavanky 8y agoWhy aren't they using LLVM :-/
- bastawhiz 8y agoThey answer this on the github: > Unstable interfaces. An LLVM JIT is already used by Rubicon. A lot of efforts in preparation of code used by RTL insns (an environment) https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch#a-few-possible-approaches-in-jit-implementation https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch#a-few...
- jashmatthews 8y agoThe new Ruby method JIT can use either GCC or clang as the backend. It uses C as an intermediate representation.
- Twirrim 8y agollvm isn't always available, doesn't support as many architectures and doesn't always give the best performance. The *nix philosophy has long been towards trying to provide choice wherever possible, so that people can use the tool that best meets their needs.
- my123 8y agoSame as the last stage of the SQL Server query optimizer then. (hey MS)
- make3 8y agothat's also what Theano did
- tbodt 8y agoWhat's the advantage over using LLVM's built-in JIT, or PyPy's JIT, or generating machine code directly, or anything else that doesn't have the overhead of spawning processes for compiling and linking? One of the goals listed is minimizing the JIT compilation time.
- pmontra 8y agoThey want to check the generated code and let people check it > The main purpose of this JIT release is to provide a chance to check if it works for your platform and to find out security risks before the 2.6 release
- jashmatthews 8y agoRuby on PyPy already exists: https://github.com/topazproject/topaz https://github.com/topazproject/topaz Performance is disappointing, though.
- obl 8y agoyeah. even LLVM is very slow for a JIT. Ask any project using LLVM as a backend for a JIT and they'll tell you it's an recurring issue. See for example https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/ https://webkit.org/blog/5852/introducing-the-b3-jit-compiler... I know very little about ruby specifically but IME for this kind of dynamic language you get most of the initial gains by : - removing (by analysis or speculation) dynamic dispatch - unboxing / avoiding allocations in the easy cases Once you've done that, you can generate pretty dumb assembly and still come out way ahead of your interpreter (and avoid very costly optimization / instruction selection / regalloc / scheduling). Most of what llvm / gcc do only make sense when you've got your code down close to whatever you would actually write in C.
- emn13 8y agoLLVM clearly wasn't designed for JIT. Don't let those letters "VM" confuse you; it's more like a machine abstraction than a virtual machine. And even that is far from water-tight. But that doesn't mean you can't use a conventional compiler stack like LLVM as a JIT and get excellent code - it' just going to take its own sweet time doing so. Can anyone think of any reasonably common stacks using LLVM as a JIT? There's mono, but that's a non-default mode; not sure if it's typically used. The python unladen-swallow experiment failed. Webkit had a short-lived FLT javascript optimization pass, but that was replaced by B3. Which is just a long-winded way to suggest that LLVM is not likely to be ideal as a JIT, at least based on what past projects have done. (Not trying to imply that writing C to disk is better, but it may well be simpler & more flexible - not worthless qualities for an initial implementation).
- handbanana 8y agoI don't see why this is bad. Many compilers generate C
- kryptiskt 8y agoNot at runtime.
- useranme 8y agoMemSQL and Smalltalk generate C at runtime.
- floatboth 8y agoWhich Smalltalk?
- dfox 8y agoSmalltalk/X can fileout packages as C projects that are then compiled by C compiler. But AFAIK this was never meant to be used as JIT and is primarily an deployment mechanism and non-ancient versions use in-process code generator implemented in Smalltalk as JIT backend. There are Common Lisp implementations that support similar mechanism of generating C code (ECL, Kyoto CL...), but I don't think any of then compiles C into .so which then gets dlopened right away as poor-mans JIT.
- kazinator 8y agoKCL generates .c files and compiles those to .o object files. I played with this year ago (via the descendant GCL: GNU Common Lisp). The load function handles object files, like COFF or whatever. It's reminiscent of the Linux kernel modules. See here, starting on P. 36: http://www.softwarepreservation.org/projects/LISP/kcl/doc/kcl-report.pdf http://www.softwarepreservation.org/projects/LISP/kcl/doc/kc... When KCL compiles a lambda expression, it generates a C file called "gazonk.lsp" and compiles that. (The above paper report is a little confusing; in some places it claims that an object file has a .o suffix, but then with regard to this gazonk implicit name, it claims that the fasl file is gazonk.fasl.)
- ethagnawl 8y ago> Oh dear god. Care to elaborate?
- saagarjha 8y agoThere are presumably better ways to get assembly out of code than generating C and passing it through a compiler frontend.
- dwheeler 8y agoThat is an unproven assumption. It's faster to hand-generate machine code straight from an interpreter than to invoke a C compiler. But that is not the only issue. As with everything else, this is a trade-off, and I'm eager to see how it works out. I can see some positive reasons to do this: 1. The Ruby developers get highly-optimized machine code, with relatively little effort on their part. Many, many man-years have been spent to make C compilers generate highly optimal code. 2. The C language, as an interface, is extremely stable, so once it works it should just keep working. Compare that to the constantly-changing interfaces of many alternatives. 3. Debugging is WAY easier. If there's a problem in generated code, it's way easier to read intermediate C code (especially after going through a pretty-printer) than many other kinds of intermediate formats, and millions of people already know it. In short, this approach means that they can very rapidly produce a system that can run tight loops very quickly, one that resists interface instability (so the approach should keep working), and one that's easy to debug (so it should be reliable). For many applications, the fact that it takes a little more time to do the compilation may be unimportant, especially since that work is embarrassingly parallelizable. I'm very interested in seeing how this plays out. If this works well for Ruby, I suspect some other language implementations will start considering using this approach. I'm sure it's not the best approach in all circumstances, but it might work very well for Ruby - and maybe for some other languages like it. "If it works, it isn't stupid".
- saagarjha 8y ago> The Ruby developers get highly-optimized machine code, with relatively little effort on their part. Many, many man-years have been spent to make C compilers generate highly optimal code. Not for machine generated code. C compilers work well on human generated code, and not as well as Ruby -> C "translations".
- dozzie 8y agoIt's the traditional method of doing a job equivalent to JIT. It has several examples in the history of computing, like SpamAssassin and Matlab (the latter if my memory serves me correctly).