35+ Years Experience Netherlands Based ⚡ Fast Response Times Ruby on Rails Experts AI-Powered Development Fixed Pricing Available Senior Architects Dutch & English 35+ Years Experience Netherlands Based ⚡ Fast Response Times Ruby on Rails Experts AI-Powered Development Fixed Pricing Available Senior Architects Dutch & English
Ruby YJIT in Productie: Hoe Je Het Activeert en Welke Prestatiewinst Je Kunt Verwachten

Ruby YJIT in Productie: Hoe Je Het Activeert en Welke Prestatiewinst Je Kunt Verwachten

TTB Software
ruby, performance
Een praktische gids voor het activeren van YJIT in Ruby 3.3 voor productie Rails-apps. Configuratie, geheugenafwegingen, echte benchmarks en monitoringtips.

YJIT wordt meegeleverd met Ruby 3.3 en is stabiel genoeg voor productie. Het activeren kost één vlag en levert doorgaans 15-25% snellere responstijden in Rails-apps op, zonder codewijzigingen.

Deze gids behandelt hoe je het aanzet, welke geheugenoverhead je kunt verwachten, en hoe je verifieert dat het werkt.

Wat YJIT Precies Doet

YJIT (Yet Another JIT) is een just-in-time compiler die sinds Ruby 3.1 in CRuby zit. Anders dan de eerdere MJIT (verwijderd in Ruby 3.3) compileert YJIT Ruby-bytecode incrementeel naar native machinecode terwijl methodes worden aangeroepen. Het is gebouwd door Maxime Chevalier-Boisvert en het Shopify Ruby-infrastructuurteam.

Het belangrijkste verschil met MJIT: YJIT compileert code lui, één basic block per keer, met zeer korte opwarmtijd. Je app start snel en wordt sneller naarmate hot paths worden gecompileerd.

Ruby 3.3 bracht flinke YJIT-verbeteringen ten opzichte van 3.2:

  • Code GC die geheugen terugwint van zelden gebruikte gecompileerde code
  • Verminderde geheugenoverhead (circa 30% minder dan YJIT in 3.2)
  • Betere ondersteuning voor Struct, keyword-argumenten en define_method
  • De --yjit-exec-mem-size-vlag voor het beheren van gecompileerd-codegeheugen

YJIT Activeren

Voeg de --yjit-vlag toe aan je Ruby-commando:

# Directe aanroep
ruby --yjit app.rb

# Via omgevingsvariabele (werkt overal)
export RUBY_YJIT_ENABLE=1

# In een Dockerfile
ENV RUBY_YJIT_ENABLE=1

# Puma-config (puma.rb)
# YJIT is procesbrede instelling, dus stel de env var in vóór Puma start

Als je met Kamal 2 deployt, voeg de omgevingsvariabele toe aan je deploy.yml:

env:
  clear:
    RUBY_YJIT_ENABLE: 1

Verifieer dat het actief is in een Rails-console:

RubyVM::YJIT.enabled?
# => true

RubyVM::YJIT.runtime_stats
# => {:inline_code_size=>1048576, :outlined_code_size=>...}

Geheugenafwegingen

YJIT gebruikt extra geheugen om gecompileerde machinecode op te slaan. In Ruby 3.3 zijn de standaardinstellingen redelijk voor de meeste apps:

Instelling Standaard Wat Het Regelt
--yjit-exec-mem-size 48 MB Max geheugen voor gecompileerde code
--yjit-call-threshold 30 Aanroepen voordat een methode wordt gecompileerd

Voor een typische Rails-app met 20 Puma-workers voegt YJIT circa 30-50 MB per workerproces toe. Op een 4 GB-server is dat 600 MB tot 1 GB extra in totaal. Voor de meeste apps de moeite waard, maar controleer je beschikbare ruimte.

Bij beperkt geheugen kun je de exec-geheugengrootte verlagen:

ruby --yjit --yjit-exec-mem-size=32 your_app.rb

De code-GC in Ruby 3.3 helpt hierbij — het ruimt gecompileerde code op die recent niet is gebruikt, zodat het geheugengebruik niet onbegrensd groeit.

Praktijkprestatiecijfers

Gemeten op een Rails 8-app (PostgreSQL, Solid Queue voor achtergrondtaken, 15 modellen, standaard CRUD + API-endpoints) met Ruby 3.3.4 op een AMD EPYC-server:

Endpoint-responstijden (p50, 1000 requests na opwarming):

Endpoint Zonder YJIT Met YJIT Verbetering
JSON API (serialisatie-intensief) 12,3 ms 9,1 ms 26% sneller
Dashboard (view-rendering) 48,7 ms 39,2 ms 19% sneller
Complexe query + transformatie 31,5 ms 25,8 ms 18% sneller
Simpele redirect 2,1 ms 1,9 ms 10% sneller

Totale Puma-doorvoer: 22% meer requests per seconde met YJIT ingeschakeld.

Deze cijfers komen overeen met Shopify’s gepubliceerde benchmarks die 15-25% verbetering laten zien op hun productie Rails-monoliet. CPU-gebonden werk profiteert het meest. Als je bottleneck databasequeries of externe API-aanroepen zijn, helpt YJIT niet bij die wachttijd — maar het versnelt wel de Ruby-code die tussen die wachttijden draait.

Wat YJIT Goed Verwerkt (en Minder Goed)

Goede kandidaten voor YJIT-versnelling:

  • View-rendering en templatecompilatie
  • JSON-serialisatie (vooral met Oj of Blueprinter)
  • ActiveRecord-objectinstantiatie
  • Stringmanipulatie en datatransformatie
  • Memoization-intensieve code — de gecachte methodebodies draaien zelf sneller

Beperkte verbetering:

  • Databasequerytijd (dat is PostgreSQL’s werk)
  • Netwerk-I/O-wachttijd
  • Bestands-I/O-operaties
  • Code die zwaar leunt op C-extensies (al gecompileerd naar native code)

YJIT Monitoren in Productie

Voeg een health-check-endpoint of periodieke taak toe om YJIT-statistieken bij te houden:

# config/initializers/yjit_stats.rb
if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
  Rails.logger.info "YJIT enabled: exec_mem_size=#{RubyVM::YJIT.runtime_stats[:inline_code_size]}"
end

# Voor gedetailleerde monitoring (bijv. in een Rake-taak of admin-endpoint)
def yjit_report
  return "YJIT not enabled" unless defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?

  stats = RubyVM::YJIT.runtime_stats(context: true)
  {
    compiled_methods: stats[:compiled_iseq_count],
    inline_code_bytes: stats[:inline_code_size],
    code_gc_count: stats[:code_gc_count],
    ratio_in_yjit: stats[:ratio_in_yjit]
  }
end

De ratio_in_yjit-statistiek is het nuttigst — het vertelt welk percentage Ruby-instructies via gecompileerde code liep versus de interpreter. Op een opgewarmde Rails-app bereikt dit doorgaans 85-95%.

YJIT vs Andere Ruby-Prestatiewinsten

YJIT is de minst arbeidsintensieve prestatieverbetering die je kunt doorvoeren. Maar stop daar niet. In volgorde van inspanning versus impact voor een typische Rails-app:

  1. YJIT activeren — één vlag, 15-25% sneller (je bent hier)
  2. Ruby GC tunen — omgevingsvariabelen, 5-15% sneller
  3. N+1-queries fixen — codewijzigingen, potentieel 10x sneller op getroffen pagina’s
  4. Database-indexen toevoegen — migraties, dramatische verbetering bij trage queries
  5. Caching toevoegen — codewijzigingen, vermindert belasting overal

Aandachtspunten en Randgevallen

Rust-toolchain voor compileren vanuit broncode. Als je Ruby van broncode compileert, vereist YJIT de Rust-compiler (1.58.0+). Voorgebouwde Ruby-pakketten (rbenv install, Docker-images) bevatten YJIT al gecompileerd.

ARM64-ondersteuning is solide. YJIT werkt op zowel x86-64 als ARM64 (Apple Silicon, AWS Graviton). Geen platformspecifieke vlaggen nodig.

Forkende servers (Puma, Unicorn). YJIT-gecompileerde code leeft in elk workerproces onafhankelijk. Na het forken van Puma-workers bouwt elke worker zijn eigen gecompileerde-codecache op. Geen probleem — de opwarming is snel (seconden, geen minuten).

Debugging. YJIT interfereert niet met binding.irb, de debug-gem of stacktraces. Foutbacktraces zien er identiek uit met of zonder YJIT.

FAQ

Is YJIT stabiel genoeg voor productie in Ruby 3.3?

Ja. Shopify draait YJIT op hun hele productie Rails-monoliet (een van de grootste Rails-apps ter wereld). GitHub gebruikt YJIT ook in productie. Ruby 3.3’s YJIT heeft meer dan een jaar productie-hardening achter de rug sinds de 3.2-release. Als je testsuite slaagt met YJIT ingeschakeld, kun je het veilig deployen.

Werkt YJIT met alle Ruby-gems?

YJIT werkt met elke gem die valide Ruby-bytecode uitvoert. C-extensies (zoals Nokogiri, pg, redis) worden niet beïnvloed — die zijn al native code. De enige gems die vroege compatibiliteitsproblemen hadden, deden ongebruikelijke dingen met TracePoint of RubyVM::InstructionSequence, en die randgevallen zijn opgelost in Ruby 3.2.

Moet ik YJIT of TruffleRuby gebruiken voor prestaties?

YJIT als je een directe verbetering wilt zonder migratiewerk. TruffleRuby kan hogere piekprestaties bereiken (2-5x op sommige benchmarks), maar vereist een andere Ruby-runtime, heeft andere gem-compatibiliteitskenmerken en gebruikt aanzienlijk meer geheugen. Voor productie Rails-apps is YJIT de pragmatische keuze.

Helpt YJIT bij achtergrondtaken?

Ja. Achtergrondtaakprocessors zoals Solid Queue en Sidekiq draaien dezelfde Ruby-code, dus CPU-gebonden taakwerk krijgt dezelfde 15-25% versnelling. Taken die voornamelijk op I/O wachten zien minimale verbetering.

#ruby #yjit #performance #jit #productie
T

About the Author

Roger Heykoop is een senior Ruby on Rails ontwikkelaar met 19+ jaar Rails ervaring en 35+ jaar ervaring in softwareontwikkeling. Hij is gespecialiseerd in Rails modernisering, performance optimalisatie, en AI-ondersteunde ontwikkeling.

Get in Touch

Share this article

Need Expert Rails Development?

Let's discuss how we can help you build or modernize your Rails application with 19+ years of expertise

Schedule a Free Consultation