RubyConf 2021

YJIT - Building a new JIT Compiler inside CRuby

YJIT - Building a new JIT Compiler inside CRuby

by Maxime Chevalier Boisvert

In this video from RubyConf 2021, speaker Maxime Chevalier Boisvert presents the development of YJIT, a Just-In-Time compiler for CRuby. The talk covers the necessity of YJIT in enhancing the performance of Ruby applications, particularly web workloads such as Ruby on Rails, which are prevalent at Shopify where the project originated.

Key points include:

- Definitions and Context: YJIT stands for Yet Another Ruby Just-In-Time compiler. It was developed to address the performance limitations of previous JIT projects, aiming for compatibility with existing Ruby code while incrementally enhancing performance.

- Development Approach: The development of YJIT is led by an open-source initiative at Shopify. The team emphasizes backward compatibility with existing Ruby features, ensuring that most Ruby code runs unmodified.

- Technical Challenges: The speaker explains the inherent difficulties in optimizing Ruby due to its dynamic typing, method dispatch complexities, and the potential for redefining core operators. These aspects introduce multiple path-checks that complicate code generation.

- Lazy Basic Block Versioning: Utilizing this technique developed during Boisvert's PhD research, YJIT compiles only the frequently executed parts of methods, allowing for efficient specialization of types at runtime. This avoids the pitfalls of whole-program analysis, facilitating faster compilation and reduced code size.

- Performance Benchmarks: YJIT demonstrates significant speed improvements over the Ruby interpreter and shows better performance than other JIT compilers like MJIT on real-world benchmarks, particularly those related to web applications. Reports suggest speedups ranging between 5% to 30%, with ongoing development aimed at improving this further.

- Future Plans: The speaker discusses upcoming features and improvements, including plans to optimize ERB template rendering, inlining, a garbage collector for code, and broader platform support.

In conclusion, while still in its early stages, YJIT shows promise for enhancing Ruby’s performance in web applications with a compatible design philosophy. The project aims to undergo further developments, aiming for integration into future Ruby releases and addressing existing limitations and performance bottlenecks.

Boisvert invites the community to engage with and test YJIT as it evolves, ensuring a vibrant collaborative development process that retains Ruby's invaluable characteristics while boosting performance.

00:00:10.000 Hello, I'm Maxime, and today I'll be telling you about YJIT. The program today includes a little bit about why we're building YJIT inside of CRuby, how it works, and then I'll present some performance results along with the next steps that we plan to take to unlock even higher performance.
00:00:15.839 So, why YJIT? The name stands for "Yet Another Just-In-Time Compiler for Ruby", as it compiles your bytecode into machine code. It's also partly because it's far from being the first attempt at building a JIT compiler for Ruby. This project was built at Shopify and it's fully open source. We hope to eventually upstream and merge it into CRuby. The objective is to produce speed-ups on real-world software; for us, real-world software means largely web workloads, such as Ruby on Rails, since we do a lot of that at Shopify.
00:00:29.279 CRuby is a very complex codebase, so the approach we've taken is incremental. We gradually build the JIT compiler, and for everything we don't support, we fall back to the Ruby interpreter. Over time, we aim to increase the number of supported features in the JIT and enhance its sophistication.
00:00:41.200 The benefits of our approach include high compatibility with all existing Ruby code and the ability to support the latest Ruby features. This project is not just me; it's led by an awesome team in the Ruby and Rails Infrastructure Group at Shopify, with multiple significant contributions from GitHub.
00:00:59.920 In the space of Ruby JITs, there have been many other projects. There's MJIT, there’s TruffleRuby, there’s Mir, there’s MagLev, and many others that are no longer maintained. I’ll briefly discuss MJIT and TruffleRuby. MJIT is already integrated into CRuby; it’s based on GCC. Some of its strengths include compatibility with the latest Ruby features, good speed-ups on smaller benchmarks, and visual support on multiple platforms. However, it performs best on smaller synthetic benchmarks and doesn’t always yield speed-ups on real-world software.
00:01:18.080 We think this is partly because GCC is not really equipped to optimize dynamically typed code, and MJIT has limited control over the compilation pipeline. It generates C code that’s then fed into GCC, which processes it in its own way. TruffleRuby, on the other hand, is an alternative implementation of Ruby based on the Truffle and GraalVM platform. It is under active development and features a powerful optimizer based on partial evaluation. TruffleRuby can offer huge speed-ups on common benchmarks and has good support for C extensions.