Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ZJIT: The Ruby 4 JIT Compiler / Ruby Release 30...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Takashi Kokubun
December 20, 2025
Programming
520
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ZJIT: The Ruby 4 JIT Compiler / Ruby Release 30th Anniversary Party
https://rubyassociation.doorkeeper.jp/events/190436
Takashi Kokubun
December 20, 2025
More Decks by Takashi Kokubun
See All by Takashi Kokubun
Lightning-Fast Method Calls with Ruby 4.1 ZJIT / RubyKaigi 2026
k0kubun
3
3.5k
一度始めたらやめられない開発効率向上術 / Findy あなたのdotfilesを教えて!
k0kubun
4
3.1k
ZJIT: The Future of Ruby Performance / San Francisco Ruby Conference 2025
k0kubun
1
130
ZJIT: Building a New JIT Compiler for Ruby / REBASE 2025
k0kubun
0
130
Deoptimization: How YJIT Speeds Up Ruby by Slowing Down / RubyKaigi 2025
k0kubun
2
4.3k
YJIT Makes Rails 1.7x faster / RubyKaigi 2024
k0kubun
7
16k
Ruby JIT Hacking Guide / RubyKaigi 2023
k0kubun
2
11k
YJIT: Dive into Ruby's JIT compiler written in Rust / Rust.Tokyo 2022
k0kubun
2
2.3k
Towards Ruby 4 JIT / RubyKaigi 2022
k0kubun
3
12k
Other Decks in Programming
See All in Programming
A2UI という光を覗いてみる
satohjohn
1
140
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
410
ふつうのFeature Flag実践入門
irof
8
4k
Creating Composable Callables in Contemporary C++
rollbear
0
150
dRuby over BLE
makicamel
2
380
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
TAKTでAI駆動開発の品質を設計する
j5ik2o
7
1.4k
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
6.2k
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.4k
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
550
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
590
Inside Stream API
skrb
1
740
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.1k
A Soul's Torment
seathinner
6
3k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.5k
WENDY [Excerpt]
tessaabrams
11
38k
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
250
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Become a Pro
speakerdeck
PRO
31
6k
sira's awesome portfolio website redesign presentation
elsirapls
0
280
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
310
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Transcript
Ruby Release 30th Anniversary Party 2025 ZJIT: The Ruby 4
JIT Compiler Takashi Kokubun / @k0kubun
self • Takashi Kokubun (@k0kubun) • Shopify: Ruby JIT team
• Ruby committer: MJIT, RJIT, YJIT, ZJIT
YJIT
YJIT • Ruby 3.1+: ruby --yjit • Rust 1.58.0+ •
Production-ready JIT compiler • Enabled by default on Rails 7.2+
https://speed.ruby-lang.org/
https://railsatscale.com/2025-01-10-yjit-3-4-even-faster-and-more-memory-e ff i cient/
ZJIT
ZJIT • Ruby 4.0+: ruby --zjit • Rust 1.85.0+ (2024
Edition) • Experimental JIT compiler • To be productionized at Ruby 4.1
None
None
None
None
Why ZJIT? • Unblock cross-instruction optimizations • Less incremental, larger
comiplation units • No memory overhead for adding optimizations
How YJIT works
How YJIT works putobject 1 getconst TWO send + leave
Bytecode
How YJIT works putobject 1 getconst TWO send + leave
Bytecode YJIT block1 Mov Reg(0), 1
How YJIT works putobject 1 getconst TWO send + leave
Bytecode YJIT block1 Mov Reg(0), 1 Context Reg(0): Integer YJIT block2 Mov Reg(1), 2 PatchPoint Constant TWO
How YJIT works putobject 1 getconst TWO send + leave
Bytecode YJIT block1 Mov Reg(0), 1 Context Reg(0): Integer YJIT block2 YJIT block3 Mov Reg(1), 2 PatchPoint Constant TWO Context Reg(0): Integer Reg(1): Integer PatchPoint Integer#+ Add Reg(0), Reg(1) Ret Reg(0)
How ZJIT works putobject 1 getconst TWO send + leave
Bytecode
How ZJIT works putobject 1 getconst TWO zjit_send + leave
Bytecode
How ZJIT works putobject 1 getconst TWO zjit_send + leave
Bytecode ZJIT HIR v1 = 1 PatchPoint TWO v2 = 2 PatchPoint Integer#+ v3 = 3 Return v3
How ZJIT works putobject 1 getconst TWO zjit_send + leave
Bytecode ZJIT HIR v1 = 1 PatchPoint TWO v2 = 2 PatchPoint Integer#+ v3 = 3 Return v3 ZJIT LIR Ret 3 PatchPoint Const TWO PatchPoint Integer#+
ZJIT IR
ZJIT IR • ZJIT IR (Intermediate Representation): • HIR: High-level
IR, new in ZJIT • LIR: Ligh-level IR, same as YJIT
HIR
HIR Optimization Passes
LIR
LIR Lowering Passes
How ZJIT compiles Ruby code
How ZJIT compiles Ruby code one: putobject 1 leave two:
putobject 2 leave three: putself send :one putself send :two send :+ leave Parse & Compile
How ZJIT compiles Ruby code one: putobject 1 leave two:
putobject 2 leave three: putself send :one putself send :two send :+ leave one: putobject 1 leave two: putobject 2 leave three: putself zjit_send :one putself zjit_send :two zjit_send :+ leave Parse & Compile Pro fi le
How ZJIT compiles Ruby code Initial HIR: fn three@/Users/k0kubun/tmp/a.rb:11: bb0():
EntryPoint interpreter v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) Jump bb2(v4) bb2(v6:BasicObject): v11:BasicObject = SendWithoutBlock v6, :one v14:BasicObject = SendWithoutBlock v6, :two v17:BasicObject = SendWithoutBlock v11, :+, v14 CheckInterrupts Return v17 one: putobject 1 leave two: putobject 2 leave three: putself send :one putself send :two send :+ leave Compile
How ZJIT compiles Ruby code Optimized HIR: fn three@/Users/k0kubun/tmp/a.rb:11: bb0():
… bb2(v6:BasicObject): PatchPoint MethodRede fi ned(one) PatchPoint NoSingletonClass(Object) v24:HeapObject[Object] = GuardType v6, HeapObject[Object] v31:Fixnum[1] = Const Value(1) PatchPoint MethodRede fi ned(two) PatchPoint NoSingletonClass(Object) v28:HeapObject[Object] = GuardType v6, HeapObject[Object] v33:Fixnum[2] = Const Value(2) PatchPoint MethodRede fi ned(Integer, +) v38:Fixnum[3] = Const Value(3) CheckInterrupts Return v38 one: putobject 1 leave two: putobject 2 leave three: putself send :one putself send :two send :+ leave Inline
How ZJIT compiles Ruby code Optimized HIR: fn three@/Users/k0kubun/tmp/a.rb:11: bb0():
… bb2(v6:BasicObject): PatchPoint MethodRede fi ned(one) PatchPoint NoSingletonClass(Object) v24:HeapObject[Object] = GuardType v6, HeapObject[Object] v31:Fixnum[1] = Const Value(1) PatchPoint MethodRede fi ned(two) PatchPoint NoSingletonClass(Object) v28:HeapObject[Object] = GuardType v6, HeapObject[Object] v33:Fixnum[2] = Const Value(2) PatchPoint MethodRede fi ned(Integer, +) v38:Fixnum[3] = Const Value(3) CheckInterrupts Return v38 one: putobject 1 leave two: putobject 2 leave three: putself send :one putself send :two send :+ leave
Hacking on ZJIT HIR
How to dump ZJIT IR • HIR: ruby --zjit-dump-hir •
LIR: ruby --zjit-dump-lir
None
tryzjit. fl y.dev
tryzjit. fl y.dev
tryzjit. fl y.dev
tryzjit. fl y.dev
tryzjit. fl y.dev
None
None
None
Future of Ruby Performance
Future of Ruby Performance • We want less C extensions
• In particular, less C → Ruby callbacks
C functions dominate execution time Only 10% of execution time
is spent in JIT code https://gist.github.com/k0kubun/5e0b3bb894e9fed9b01e25fd25e8bea5
C functions dominate execution time Some interpreter implementations are used
for reasons https://gist.github.com/k0kubun/5e0b3bb894e9fed9b01e25fd25e8bea5 Complicated argument setup, C → Ruby calls, megamorphic callsite Instance variables: megamorphic callsite
C functions dominate execution time 15% is spent on DB
queries https://gist.github.com/k0kubun/5e0b3bb894e9fed9b01e25fd25e8bea5
C functions dominate execution time 15% is spent on allocation
and garbage collection https://gist.github.com/k0kubun/5e0b3bb894e9fed9b01e25fd25e8bea5
C functions dominate execution time Many methods are implemented in
C https://gist.github.com/k0kubun/5e0b3bb894e9fed9b01e25fd25e8bea5
C functions dominate execution time • Methods written in C
• C → Ruby calls • Megamorphic callsites Reasons why that happens
https://github.com/ruby/ruby/pull/3281
Conclusion • ZJIR unblocks cross-instructions optimizations • Enjoy hacking on
ZJIT HIR • Stay tuned for Ruby 4.1 ZJIT