Live data from Hacker News

Ruby 2.6.0-preview2 released with JIT

ruby-lang.org

131–136 of 136 posts

Re: Ruby 2.6.0-preview2 released with JIT

#131
post #129
post #128

Earlier quoted context omitted.

What contradiction? Google should have paid Sun instead of playing a Microsoft's move fostering Sun's downfall, period. And in doing so, Android would have been JavaSE compliant plus whatever additional libraries they would think to drop on top of it.

How do you come to the idea that having more Java devices available, even if not 100% compatible, would have in any way caused harm to Sun? And then even that much that it killed the company? On top of that, I don't see for what google would have had an obligation to pay. Contradiction: Google broke some imaginary copyright by re-implementing APIs, but Google is bad because the re-implementation was not 100% equal to…

Because those devices run Android Java, which Sun saw $0, thus not able to capitalize on it to pay their bills.

1 - Google did not pay for Java licenses, when it should. Even Andy Rubin admits that on his emails.

2 - To this day Android is not Java SE compliant, thus creating a fragmentation between Android Java and Java. Just like Sun managed to prevent with J++

3 - Being a Java license as Google avoided to be, and still isn't (many Java APIs are not yet available on Android), would have required Android to be fully Java SE compliant

So to conclude, Google tricked Sun and fragmented the Java eco-system.

They should pay and provide a 100% Java SE compliant implementation, or be honest about it and fully migrate to Kotlin, Dart or whatever they feel like it.

Re: Ruby 2.6.0-preview2 released with JIT

#132

> 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.

> Oh dear god. Care to elaborate?

Overhead. It converts its IR to C; dumps that to disk; the C compiler loads the code back from the disk; the frontend parses the code (if not done carefully maybe CPP is also invoked); the compiler dumps the generated code to disk again; and then presumably dlopen loads the code back from disk again. There's also the overhead of spawning a separate compiler process. A better way would be to directly generating code to memory and link it. This is of course trickier, but is also what libraries such as LLVM's JIT infrastructure and libjit are built for. If you need more performance (i.e. LLVM's JIT is too slow for you), you roll your own infrastructure to do this -- which is what JVM and V8 do.

Re: Ruby 2.6.0-preview2 released with JIT

#133

Earlier quoted context omitted.

> Oh dear god. Care to elaborate?

Overhead. It converts its IR to C; dumps that to disk; the C compiler loads the code back from the disk; the frontend parses the code (if not done carefully maybe CPP is also invoked); the compiler dumps the generated code to disk again; and then presumably dlopen loads the code back from disk again. There's also the overhead of spawning a separate compiler process. A better way would be to directly generating code t…

There's definitely a run-time overhead, but it may not be that bad in practice. Details on the Ruby JIT implementation are here: https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch#mjit-...

They don't "dump to disk", if you mean an actual storage device. By default they store data to a "file system in memory" (a tmpfs), so it never gets written to a long-term storage device (not even an SSD). Even if you do "dump to disk", on a modern OS storing things in a file just puts it in memory and schedules it for eventual long-term storage. Of course, doing things this way has overheads, but it may not be so bad.

The C frontend has to parse things, of course, but it looks like they're heavily optimizing this. "To simplify JIT implementation the environment (C code header needed to C code generated by MJIT) is just an vm.c file. A special Ruby script minimize the environment (Removing about 90% of the declarations). One worker prepares a precompiled code of the minimized header, which starts at the MRI execution start".

Their current results are that "No Ruby program real time execution slow down because of MJIT" and "The compilation of small ISEQ takes about 50-70 ms on modern x86-64 CPUs". You're of course using more CPU (to do the compilations in parallel), and you have to have a compilation suite available at runtime, but in many circumstances that is perfectly reasonable.

IIRC, the gcc C compiler doesn't generate machine code itself either; it generates assembly code, which is then farmed out to a separate assembly process (using using GNU assembler aka GAS). Farming out compilation work to other processes is not new.

It seems to me that this is a really plausible trade. This approach means that they can add a just-in-time compiler "relatively" quickly, and one that should produce pretty decent code once they add some actual optimizations (because it's building on very mature C compilers). The trade-off is that this approach requires more run-time CPU and time to create each compiled component (what you term as overhead). For many systems, this is probably an appropriate trade. As I posted earlier, I'm very interested in seeing how well this works - I think it's promising.

Re: Ruby 2.6.0-preview2 released with JIT

#134

Earlier quoted context omitted.

That 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 hav…

> 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".

> Not for machine generated code. C compilers work well on human generated code, and not as well as Ruby -> C "translations".

That depends on the machine generated code. C compilers are optimized for whatever the C compiler authors perceive as a common construct. If the generated C code uses constructs similar to what humans do, it's often quite good. If not, you can change the code that generates C, or in some cases you can convince the C compiler authors to optimize that situation as well.

Re: Ruby 2.6.0-preview2 released with JIT

#135
post #21

> We’re going to implement method iniling in JIT compiler, which is expected to increase Ruby’s performance in order of magnitude An order of magnitude as in .. 10x? This seems too good to be true. Half the arguments against Rails melt away like butter if that's truly the case. Anyone with a better understanding of the details care to comment on the likelihood of these performance gains being actually realised, and i…

Sinatra + Sequel is already very competitive in web performance with Go + Gin[1]. It's the Rails convenience stuff which slows things down massively. MJIT could probably bring Rails in line with Sinatra though. Between Ruby 1.8 and 2.5, performance has improved around 13x in tight loops[2]. The Rails performance issue has been massively overblown since 1.9 was released. Ruby 1.8 was a tree walking interpreter, so the…

Ruby has made huge strides to be sure. However this is a bit hyperbolic IMHO.

Golang plus gin, sure. However there are other Go frameworks on the charts that blast the Ruby competition out of the water. Ruby isn't really on the podium at all with C, C++, Rust, Golang, C#, and Java about an order of magnitude out in the lead on fortunes.

Martini isn't much of a framework itself either, so lets forget the full featured nonsense. Almost none of the ecosystem is in play with these benchmarks. You could build a system up around fasthttp just as well as net/http, and ASP.NET certainly can't be accused of being a for-purpose contender.

The most impressive thing IMHO is how well Ruby is doing on maximum latency. I can't quite reconcile that considering fasthttp is pretty much zero-allocation and golangs stop the world is in the microseconds.. Pretty impressive.

Re: Ruby 2.6.0-preview2 released with JIT

#136
post #135

Earlier quoted context omitted.

Sinatra + Sequel is already very competitive in web performance with Go + Gin[1]. It's the Rails convenience stuff which slows things down massively. MJIT could probably bring Rails in line with Sinatra though. Between Ruby 1.8 and 2.5, performance has improved around 13x in tight loops[2]. The Rails performance issue has been massively overblown since 1.9 was released. Ruby 1.8 was a tree walking interpreter, so the…

Ruby has made huge strides to be sure. However this is a bit hyperbolic IMHO. Golang plus gin, sure. However there are other Go frameworks on the charts that blast the Ruby competition out of the water. Ruby isn't really on the podium at all with C, C++, Rust, Golang, C#, and Java about an order of magnitude out in the lead on fortunes. Martini isn't much of a framework itself either, so lets forget the full featured…

> The most impressive thing IMHO is how well Ruby is doing on maximum latency. I can't quite reconcile that considering fasthttp is pretty much zero-allocation and golangs stop the world is in the microseconds.. Pretty impressive.

Fast GC is critical to Ruby performance so a ton work went into it. Ruby 2.2+ has a very short STW phase thanks to generational GC + incremental marking.

Post reply on HN