Benchmarking CRuby, MJIT, YJIT, JRuby, and TruffleRuby
eregon.me
eregon.me
Still a bit puzzled why we haven't seen any headlines about major savings.
Some things are expected to be slower, for instance constantly redefining (monkey-patching) methods or constants is slower on TruffleRuby, but that's typically because the program is broken and so it'd be slow on CRuby as well.
# With MRI ruby-2.6.6
Measuring [loading ruby dependencies] 3.560960 2.507366 6.075755 ( 6.154898)
Measuring [loading configuration yaml] 0.823779 0.085605 0.909384 ( 0.931334)
Measuring [creating objects from YAML and performing filtering] 0.499576 0.042023 0.541599 ( 0.552427)
Measuring [object validation] 2.362139 0.226133 2.588272 ( 2.674958)
Total time: 7.246786 2.861230 10.115445 ( 10.314025)
# With truffleruby-21.3.0
Measuring [loading ruby dependencies] 91.818473 5.598149 97.427109 ( 36.676471)
Measuring [loading configuration yaml] 28.032630 0.811577 28.844207 ( 8.616437)
Measuring [creating objects from YAML and performing filtering] 14.952781 0.479387 15.432168 ( 4.634803)
Measuring [object validation] 86.747057 2.788266 89.535323 ( 28.324909)
Total time: 221.595872 9.680172 231.286531 ( 78.264226)
Persisting the JITed code is what we think can solve the slower startup entirely: https://www.graalvm.org/graalvm-as-a-platform/language-imple... Also other things mentioned in https://eregon.me/blog/2022/01/06/benchmarking-cruby-mjit-yj...
However, we also ran into many problems that felt like we were the first to encounter them (few or no similar reports on project bug lists or StackOverflow etc.) which is never fun if you're under any kind of pressure to deliver.
In hindsight, if I had something small and reasonably isolated (a microservice?), it could make sense to use JRuby or Truffle (if you need some JVM lib; if it's purely for performance reasons I'd just grab a different language for that microservice). But for a larger app that pays the bills, I'd stick with the well-trod path (at the time that was MRI, Unicorn, single-threaded).
If you ever have any issues with JRuby again, please let us know. We spend most of our time supporting users and want them to have a good experience.
> Nearly all of Stripe’s codebase is implemented in Ruby running on the default Ruby VM (YARV). Not only did we not need Java VM-level interoperability, choosing either alternative Ruby implementation would have made for a difficult migration path. Stripe relies heavily on gems with native extensions, and as you can imagine, a multi-million line Ruby codebase over time starts to depend on Ruby-the-implementation, not just Ruby-the-language.
¹: https://sorbet.org/blog/2021/07/30/open-sourcing-sorbet-comp...
Keeping up compatibility (while keeping things efficient) is a lot of work, TruffleRuby tries to reduce that by reusing as much as possible existing code, including reusing C extensions shipped with CRuby.
JRuby remains the only alternative Ruby to see large-scale production deployment.
Python 3 and Ruby 3 (with no jit) both take about 90 seconds on my computer.
Ruby 3.1 with --YJIT takes about 35 seconds.
TruffleRuby takes 9 seconds (!!)
JS (Chrome) takes 8 seconds.
C++ takes just over a second and C is about a second even.
n-body
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
spectral-norm
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Numerical to string formatting is a bit different too. Which makes the above problem even worse, compounded by how frequently ruby web code goes string to numbers to string to numbers.
Regexes behave differently if they worked at all.
There were compatibility issues with BigDecimal, but TruffleRuby now uses the C extension, hence it should be exactly the same behavior as CRuby.
> Numerical to string formatting is a bit different too.
AFAIK that was fixed years ago if you mean float formatting.
> Regexes behave differently if they worked at all.
TruffleRuby always used Joni, which is literally a translation of CRuby's Regexp engine to Java (by the JRuby team), so that is very surprising and I have a really hard time to believe it. At least "Regexes behave differently if they worked at all" seems harsh and highly inaccurate to me. There likely were a couple Regexp issues but the generalization seems wildly exaggerated.