Slide 1

Slide 1 text

JRuby 10! Ruby 3.3 on the Modern JVM

Slide 2

Slide 2 text

Who Am I • Charles Oliver Nutter • @headius(@mastodon.social) • [email protected] • JRuby developer for 20 years • Seeking new sponsorship for JRuby

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

What is JRuby? • Ruby on the Java Virtual Machine (JVM) • Ruby implementation fi rst, JVM language second • Many bene fi ts from JVM ecosystem • Ruby code should "just work" • Different extension API, no forking, parallel threads • Thousands of production users, 17 years of real-world use

Slide 5

Slide 5 text

JVM Advantage • World class garbage collectors (many choices) • Native JIT (JRuby was the fi rst JIT for Ruby) • Also inlines JRuby extensions, JVM libraries • Monitoring and pro fi ling tools (many choices, most are Free) • Deploy anywhere (no compiling, no C code, many platforms) • Thousands of JVM developers making it better

Slide 6

Slide 6 text

JRuby 9.4 • Stable release, supported until 2026(?) • Ruby 3.1 compatible • Java 8+ compatible • rvm, ruby-install, ruby-build, OS packages, Windows installer, Docker images, tarballs, zips, whatever • Thousands of users, billions of requests worldwide

Slide 7

Slide 7 text

Example Users • Kami: homework app for teachers, students • Millions of PDFs processed by JRuby every day • Datek: point-of-sale, airplane refueling terminals, ad kiosks • Looker: business analytics platform from Google • Kinetic Data: business portal and automation platform • Let us know if you use JRuby!

Slide 8

Slide 8 text

JRuby Compiler Pipeline Ruby (.rb) JIT Java Instructions (java bytecode) Ruby Instructions (IR) parse interpret interpreter interpret C1 compile native code better native code java bytecode interpreter execute C2 compile Java Virtual Machine JRuby Internals

Slide 9

Slide 9 text

Composition of CRuby Ruby parser Compiler and IR Core classes Standard library Native/C Ruby Rust

Slide 10

Slide 10 text

Native/C Ruby Composition of JRuby Ruby parser Compiler and IR Core classes Standard library Java

Slide 11

Slide 11 text

Better Extension Performance 0M 0.3M 0.6M 0.9M 1.2M small medium large 0.13 0.29 1.1 0.06 0.11 0.72 MRI (oj) JRuby (oj) Millions of loads per second (higher is better)

Slide 12

Slide 12 text

Better Scaling requests per second per MB of memory (16-way concurrency) 0rps/mb 0.45rps/mb 0.9rps/mb 1.35rps/mb 1.8rps/mb 1.72 rps/MB 0.92 rps/MB 0.8 rps/MB CRuby CRuby + YJIT JRuby 300MB heap One JRuby process can run your entire site

Slide 13

Slide 13 text

Graphics GUIs and Games Shoes 4 Glimmer Minecraft

Slide 14

Slide 14 text

JRuby on Android ruboto.org

Slide 15

Slide 15 text

JRuby 10

Slide 16

Slide 16 text

JRuby 10! • Major leap forward • Ruby 3.3 3.4 support, Java 17 (or 21) minimum • New Prism parser with complete language features • Targeted optimization across the board • Our biggest jump since JRuby 9000 (9.0.0.0) • Now is the time to contribute! 𝕏

Slide 17

Slide 17 text

Ruby 3.4 Support

Slide 18

Slide 18 text

Ruby 3.4 Compatible • Language specs: 98.6% passing • Core specs: 97% passing • Same default and bundled gems, some with JRuby extensions • Releasing right after CRuby 3.4 • And preview releases maybe?

Slide 19

Slide 19 text

Ruby Parser • Two parsers: Java (port of C version) and Prism (new C-based) • Future is Prism by default • Ship native library for most platforms • Ship WASM build that runs on JVM without native code • Prism already integrated in JRuby 9.4!

Slide 20

Slide 20 text

Optimization

Slide 21

Slide 21 text

Compatibility Before Optimization • Compatibility fi rst • Keep up with Ruby features • Support users and fi x bugs • Now: caught up with CRuby, more compatible than ever • Finally doing long-planned optimizations!

Slide 22

Slide 22 text

Frame-aware Methods • Some methods can read/write the caller frame • __method__/__callee__ need called method's name • block_given? needs passed block • JVM does not let us access frame (security etc) • Put frame on heap, expensive and breaks optimizations • Optimized: pass frame data on stack, special call site

Slide 23

Slide 23 text

__method__ performance 0M iter/s 2.25M iter/s 4.5M iter/s 6.75M iter/s 9M iter/s __method__ 8.4M 4.4M 2.5M CRuby JRuby 9.4 CRuby YJIT JRuby 10

Slide 24

Slide 24 text

ALOAD 0 ALOAD 4 ALOAD 5 ALOAD 2 GETSTATIC org/jruby/runtime/Visibility.PUBLIC : Lorg/jruby/runtime/Visibility; ALOAD 3 INVOKEVIRTUAL org/jruby/runtime/ThreadContext.preMethodFrameOnly (Lorg/jruby/RubyModul ALOAD 0 ALOAD 2 INVOKEDYNAMIC callVariable:__method__(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runt // handle kind 0x6 : INVOKESTATIC org/jruby/ir/targets/indy/SelfInvokeSite.bootstrap(Ljava/lang/invoke/MethodHandles$L // arguments: 0, 0, "-e", 1 ] Load method name on stack Update frame on heap Normal call to __method__

Slide 25

Slide 25 text

InvokeDynamic • JVM's special sauce for dynamic languages • De fi ne a new "instruction" • Write code to connect call site to instruction logic • JIT optimizes like static JVM bytecode • Most JRuby optimizations use InvokeDynamic

Slide 26

Slide 26 text

ALOAD 0 ALOAD 2 ALOAD 5 INVOKEDYNAMIC callVariable:__method__(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runt // handle kind 0x6 : INVOKESTATIC org/jruby/ir/targets/indy/FrameNameSite.frameNameBootstrap(Ljava/lang/invoke/MethodH // arguments: "-e", 1 ] Load method name on stack Special call to name-aware instruction FrameNameSite calls frameless __method__ with name or makes normal method call

Slide 27

Slide 27 text

__method__ performance 0M iter/s 2.25M iter/s 4.5M iter/s 6.75M iter/s 9M iter/s __method__ 8.4M 4.4M 2.5M CRuby JRuby 9.4 CRuby YJIT JRuby 10

Slide 28

Slide 28 text

__method__ performance 0M iter/s 10M iter/s 20M iter/s 30M iter/s 40M iter/s __method__ 36.30M 8.40M 4.40M 2.50M CRuby JRuby 9.4 CRuby YJIT JRuby 10

Slide 29

Slide 29 text

block_given? performance 0M iter/s 5M iter/s 10M iter/s 15M iter/s 20M iter/s block_given? 18.9M 6.4M 2.6M CRuby JRuby 9.4 CRuby YJIT JRuby 10

Slide 30

Slide 30 text

block_given? performance 0M iter/s 75M iter/s 150M iter/s 225M iter/s 300M iter/s block_given? 241.5M 18.9M 6.4M 2.6M CRuby JRuby 9.4 CRuby YJIT JRuby 10

Slide 31

Slide 31 text

String Interpolation • Too much bytecode to compile interpolated string • Harder to inline, slower to warm up • Optimized: special call site with static string and pattern • Small bytecode, better optimization

Slide 32

Slide 32 text

"foo#{a}bar#{b}baz#{c}"

Slide 33

Slide 33 text

ALOAD 0 INVOKEDYNAMIC bufferString(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyStr ALOAD 0 INVOKEDYNAMIC frozen(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyString; INVOKEVIRTUAL org/jruby/RubyString.cat19 (Lorg/jruby/RubyString;)Lorg/jruby/Rub ALOAD 8 INVOKEVIRTUAL org/jruby/RubyString.appendAsDynamicString (Lorg/jruby/runtime/bu ALOAD 0 INVOKEDYNAMIC frozen(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyString; INVOKEVIRTUAL org/jruby/RubyString.cat19 (Lorg/jruby/RubyString;)Lorg/jruby/Rub ALOAD 9 INVOKEVIRTUAL org/jruby/RubyString.appendAsDynamicString (Lorg/jruby/runtime/bu ALOAD 0 INVOKEDYNAMIC frozen(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyString; INVOKEVIRTUAL org/jruby/RubyString.cat19 (Lorg/jruby/RubyString;)Lorg/jruby/Rub ALOAD 10 INVOKEVIRTUAL org/jruby/RubyString.appendAsDynamicString (Lorg/jruby/runtime/bu ASTORE 11

Slide 34

Slide 34 text

0001 putobject "foo" 0003 getlocal_WC_0 a@0 0005 dup 0006 objtostring 0008 anytostring 0009 putobject "bar" 0011 getlocal_WC_0 b@1 0013 dup 0014 objtostring 0016 anytostring 0017 putobject "baz" 0019 getlocal_WC_0 c@2 0021 dup 0022 objtostring 0024 anytostring 0025 concatstrings 6

Slide 35

Slide 35 text

ALOAD 0 INVOKEDYNAMIC bufferString(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyStr ALOAD 0 INVOKEDYNAMIC frozen(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyString; INVOKEVIRTUAL org/jruby/RubyString.cat19 (Lorg/jruby/RubyString;)Lorg/jruby/Rub ALOAD 8 INVOKEVIRTUAL org/jruby/RubyString.appendAsDynamicString (Lorg/jruby/runtime/bu ALOAD 0 INVOKEDYNAMIC frozen(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyString; INVOKEVIRTUAL org/jruby/RubyString.cat19 (Lorg/jruby/RubyString;)Lorg/jruby/Rub ALOAD 9 INVOKEVIRTUAL org/jruby/RubyString.appendAsDynamicString (Lorg/jruby/runtime/bu ALOAD 0 INVOKEDYNAMIC frozen(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyString; INVOKEVIRTUAL org/jruby/RubyString.cat19 (Lorg/jruby/RubyString;)Lorg/jruby/Rub ALOAD 10 INVOKEVIRTUAL org/jruby/RubyString.appendAsDynamicString (Lorg/jruby/runtime/bu ASTORE 11

Slide 36

Slide 36 text

ALOAD 0 ALOAD 8 ALOAD 9 ALOAD 10 INVOKEDYNAMIC buildDynamicString(Lorg/jruby/runtime // handle kind 0x6 : INVOKESTATIC org/jruby/ir/targets/indy/BuildDynamicStringSite. // arguments: "foo", "UTF-8",

Slide 37

Slide 37 text

BuildDynamicString • Allocate large enough buffer for all elements • Pro fi le to pick "right size"? • Static strings copy directly into buffer • "Appendable" objects copy directly into buffer • Only non-String objects create temporary strings

Slide 38

Slide 38 text

0 7.5 15 22.5 30 "#{n}" "foo#{n}" "#{n}bar" "#{n}#{n}" "foo#{n}bar" "#{n}bar#{n}" "#{n}#{n}bar" "foo#{n}#{n}" "#{n}#{n}#{n}" "foo#{n}bar#{n}baz" "foo#{n}bar#{n}baz#{n}" "#{x}#{x}#{x}#{x}#{x}" "#{x}#{x}#{x}#{x}#{x}#{x}#{x}#{x}#{x}#{x}" CRuby 3.4 YJIT JRuby 10

Slide 39

Slide 39 text

Many Opportunities • Special variables like $~ and $_ • Read-only closure variables passed on stack • Block-receiving methods inlined with block • Smarter object shapes for instance variables, strings, arrays • Inline super calls, metaprogramming, and many others • JRuby 10 will be faster and warm up more quickly!

Slide 40

Slide 40 text

Modern JVM

Slide 41

Slide 41 text

Better Fibers

Slide 42

Slide 42 text

Fibers with Project Loom • Thread-based fi bers don't scale • Enumerators use fi bers • Structured concurrency is coming • Loom brings fi bers to JVM • Easily handles thousands of fi bers • Faster context-switching

Slide 43

Slide 43 text

Faster FFI

Slide 44

Slide 44 text

FFI With Project Panama • Foreign function interface (FFI) • With JVM help to make direct calls • Foreign memory API • JVM-assisted access, lifecycle • Make FFI calls as fast as C ext • Time to get rid of C extensions!

Slide 45

Slide 45 text

Faster Startup and Warmup

Slide 46

Slide 46 text

JRuby Compiler Pipeline Ruby (.rb) JIT Java Instructions (java bytecode) Ruby Instructions (IR) parse interpret interpreter interpret C1 compile native code better native code java bytecode interpreter execute C2 compile Java Virtual Machine JRuby Internals

Slide 47

Slide 47 text

Startup Time • Very hard for JRuby, due to JVM design • Project CRaC: checkpoint a running JVM and restore it • Warm up JRuby and start running immediately! • Linux and Docker for now, more platforms later • Project Leyden: ahead-of-time compile for OpenJDK • JVM JIT server: start with JIT code from previous run

Slide 48

Slide 48 text

ruby -e 1 0s 0.45s 0.9s 1.35s 1.8s -e 1 0.21s 1.271s 1.686s 0.053s CRuby 3.2 JRuby 9.4 JRuby 9.4 --dev JRuby 9.4 CRaC

Slide 49

Slide 49 text

rails new testapp --skip-bundle 0s 1.5s 3s 4.5s 6s rails new testapp --skip-bundle 0.89s 2.7s 5.918s 0.314s CRuby JRuby JRuby --dev JRuby CRaC

Slide 50

Slide 50 text

Future of JRuby

Slide 51

Slide 51 text

JRuby Future • JRuby 9.4 continues to stabilize, moving to maintenance mode • JRuby 10 this year bringing 3.4, faster execution, new JVM stuff • Big announcement for the fi rst time today...

Slide 52

Slide 52 text

A New Path for JRuby! • JRuby's time at Red Hat is coming to an end • We are grateful for 12 years of funding • Nothing to do with JRuby, just new priorities at Red Hat • We want to keep working on JRuby for you! • Seeking sponsors, patrons to keep project going • Commercial support offering coming soon!

Slide 53

Slide 53 text

JRuby Support! • Working on a support company for JRuby • Various tiers from "supporter" to "enterprise" levels • Prioritized bug fi xes, optimizations • Help with pro fi ling, deployment, and more • Please contact us at [email protected] for more information!

Slide 54

Slide 54 text

Thank You! • Charles Oliver Nutter • [email protected] • @headius(@mastodon.social) • Please email [email protected]! • https://github.com/jruby/jruby • https://www.jruby.org • JRuby room on [matrix]