Slide 1

Slide 1 text

Ruby on the Modern JVM

Slide 2

Slide 2 text

Who Am I • Charles Oliver Nutter • @headius(@mastodon.social) • [email protected] • JRuby developer since 2004 • Full-time JRuby and JVM language advocate since 2006

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 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 6

Slide 6 text

What Is Important? • Usability: compatibility, startup time, warmup time • Runtime: GC, JIT, monitoring, pro fi ling, concurrency • Platform: mobile, server, desktop, integration, deployment • Performance: straight line, scaling, parallelism, resource usage • Approachable: easy to contribute with any level of experience • Different applications needs different things

Slide 7

Slide 7 text

Getting Started

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

JRuby Install • Install a JDK • Latest Java recommended (Java 21 is LTS) • Java 8 supported for 9.4 and lower • Install JRuby • Recommended: Ruby installer, system package, Docker image • Download tarball/zip or Windows installer

Slide 10

Slide 10 text

Test it out! [] ~ $ rvm use jruby Using /Users/headius/.rvm/gems/jruby-9.4.5.0 [] ~ $ irb >> runtime = java.lang.Runtime.runtime => # >> runtime.available_processors => 8 >> runtime.free_memory => 91420584 >>

Slide 11

Slide 11 text

Ruby Compatibility • JRuby 9.4 is Ruby 3.1 compatible • 98% of language specs passing • Nearly complete core + stdlib features from 2.7, 3.0 and 3.1 • JRuby 9.3 (Ruby 2.6 compat) maintaned through 2023 • Compatibility before performance!

Slide 12

Slide 12 text

JRuby Architecture

Slide 13

Slide 13 text

JVM Language • JRuby defers many hard problems to the JVM platform • Native threading and VM internals • Memory management and garbage collection • Native JIT and optimizations • JRuby is a little VM on top of a big VM

Slide 14

Slide 14 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 15

Slide 15 text

JVM JIT • HotSpot JIT is most widely deployed • Multi-tier optimizations, fast and stable • Battle-tested for 20 years, dozens of contributors today • Graal JIT: newer, more aggressive optimizations • OpenJ9 JIT (IBM JDK): of fl ine AOT, JIT servers, checkpointing

Slide 16

Slide 16 text

Indy on Java 8, 11, 17 Times faster than JRuby Java 8 no indy 0 1.25 2.5 3.75 5 Mandelbrot Red/Black 4.05x 3.92x 3.74x 3.68x 3.72x 1.97x Java 8 indy Java 11 indy Java 17 indy 3.28x CRuby JIT 1.86x CRuby JIT

Slide 17

Slide 17 text

Indy + Graal JIT Times faster than JRuby Java 8 no indy 0 4 8 12 16 Mandelbrot Red/Black 3.13x 15.7x 4.05x 3.92x 3.74x 3.68x 3.72x 1.97x Java 8 indy Java 11 indy Java 17 indy Graal CE indy Escape analysis But not always better

Slide 18

Slide 18 text

JVM GC • Many options to tune JVM GCs • Heap size: small or large? • Throughput: faster allocations or shorter pause times? • Working set: large in-memory or mostly new objects? • Many options in standard OpenJDK • Serial, Parallel, G1, ZGC, Shenandoah, MMtk

Slide 19

Slide 19 text

Visual VM

Slide 20

Slide 20 text

Core and Standard Library • Core class like String and Array mostly "native" Java • Small pieces moving to Ruby over time • Standard library largely shared with CRuby • Pure-Ruby libraries are the same (rss, rake, rubygems...) • Extension libraries have JRuby versions (digest, psych, json...) • Many thanks to @hsbt and others for working with us!

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

Monitoring and Pro fi ling • VisualVM: GUI console for basic JVM monitoring • JDK Flight Recorder: always-on monitoring with pro fi ling options • Low-overhead 1% to 5%, built into OpenJDK • JDK Mission Control: GUI client for Flight Recorder data • https://adoptium.net/jmc/

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

Many Ways to Contribute • Wide array of languages (Java, Ruby, Kotlin, Scala, Clojure, C...) • Straightforward codebase (RubyString, RubyArray, etc) • Many levels of complexity (simple methods up to compiler optz) • Non-coding options (run tests, report issues, try things out) • We need your help!

Slide 26

Slide 26 text

Performance and Scaling

Slide 27

Slide 27 text

Scaling Applications • Classic problem on CRuby/MRI • No concurrent threads, so we need worker processes • Processes duplicate runtime state and waste resources • JRuby is an excellent solution • Multi-threaded single process runs your entire site • World-class GC uses resources better

Slide 28

Slide 28 text

Baseline Rails App • Scaffolded "blog" application on PostgreSQL, Puma • IBM VPC instance: 8 vCPU, 32GB • CRuby 3.2, 16 workers • JRuby 9.4: 16 threads • Database, siege benchmark driver on same instance

Slide 29

Slide 29 text

Requests per second 0 450 900 1350 1800 60s siege iteration 1 2 3 4 5 6 7 JRuby CRuby 3.2 CRuby 3.2 + YJIT

Slide 30

Slide 30 text

requests per second (higher is better) 0rps 450rps 900rps 1350rps 1800rps 1,550rps 1,280rps 1,705rps JRuby 9.4 CRuby 3.2 CRuby + YJIT

Slide 31

Slide 31 text

Memory • JRuby: 3.4GB RSS • JRuby with 300MB heap: 955MB RSS • JRuby G1: 1.6G • CRuby: 16x 103MB = 1.6GB • CRuby YJIT: 16x 125MB = 2GB

Slide 32

Slide 32 text

requests per second (higher is better) 0rps 450rps 900rps 1350rps 1800rps 1,643rps 1,550rps 1,280rps 1,705rps JRuby 9.4 CRuby 3.2 CRuby + YJIT JRuby 300MB heap

Slide 33

Slide 33 text

RPS 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.775 rps/MB 0.8 rps/MB 0.501 rps/MB JRuby 9.4 CRuby 3.2 CRuby + YJIT JRuby 300MB heap

Slide 34

Slide 34 text

RPS per MB of memory (160-way concurrency) 0rps 3.5rps 7rps 10.5rps 14rps 13.692 rps/MB 0.775 rps/MB 0.8 rps/MB 4.871 rps/MB JRuby 9.4 CRuby 3.2 CRuby + YJIT JRuby 300MB heap $$$$

Slide 35

Slide 35 text

GUIs, Graphics, and Games

Slide 36

Slide 36 text

GUI Libraries • Swing, built into JDK • Clean, cross-platform, easy to build simple UIs • Scalable Windowing Toolkit (Eclipse SWT) • Native widgets, WebKit browser component, rich ecosystem • JavaFX (via JRubyFX, github/jruby/jrubyfx) • Scene-based, vector drawing, event-driven modern UI library

Slide 37

Slide 37 text

Shoes 4

Slide 38

Slide 38 text

Glimmer • Glimmer GUI DSL • Multiple backends (SWT, GTK, ...) • JRuby + SWT is the most mature • JRuby makes cross-platform GUI much easier! • Works same everywhere • GUI libraries shipped with gem

Slide 39

Slide 39 text

JRubyFX • JRuby wrapper for JavaFX • Supports FXML layout or direct widget scripting • Deployable on mobile (Android)

Slide 40

Slide 40 text

Fun Stuff event(:player_egg_throw) do |e| e.hatching = true e.num_hatches = 120 e.player.mesg "hatched" end Purugin https://github.com/enebo/Purugin

Slide 41

Slide 41 text

GUIs... like Android?

Slide 42

Slide 42 text

Ruboto: JRuby on Android • ruboto.org, https://github.com/ruboto/ruboto • Actively used for commercial projects today • Build interface with GUI builder, wire it up with Ruby code • Neglected a bit but being updated for JRuby 9.4 now!

Slide 43

Slide 43 text

Ruboto IRB • IRB in JRuby on Android! • Plus an editor and script runner • Not currently in the store, but we will republish soon! • Search for "Ruboto Core" and "Ruboto IRB" APKs

Slide 44

Slide 44 text

Updated Ruboto! • We are updating Ruboto! • JRuby 9.4, with Ruby 3.1 support • Latest versions of Android • Still a few bugs to work through • https://github.com/ruboto/JRuby9k_POC • jruby_9_4 branch • bundle install ; rake assemble

Slide 45

Slide 45 text

Advanced JVM Features

Slide 46

Slide 46 text

Fibers

Slide 47

Slide 47 text

Fibers • "virtual threads", "threadlets", "coroutines" • Threads depend on OS/CPU to switch contexts • Fibers explicitly switch to another call stack on same Thread • Switch automatically at IO or lock boundaries • Many fi bers to one OS thread, so fewer resources needed • See Vishwa and Ishani's concurrency talk!

Slide 48

Slide 48 text

Thread 2 Fiber 2 Fiber 1 hands o ff to Fiber 2, which runs immediately etc Execution fl ow Fiber 1 Wait for IO Accept socket Wait for IO Accept socket Handle request Send response etc Thread 1 Wait for IO Accept socket Thread gets descheduled from CPU but still waiting for IO Handle request Send response

Slide 49

Slide 49 text

Fibers on JRuby • No native JVM fi bers, so we have to simulate it with threads! • Very resource-intensive • No more than a couple thousand fi bers at a time • Slow context-switching, at the mercy of OS/CPU • Ruby world moving toward tens of thousands of fi bers...

Slide 50

Slide 50 text

5.times do t = Time.now # create 100k fibers ary = 100_000.times.map { Fiber.new { } } # resume and complete 100k fibers ary.each(&:resume) p Time.now - t end

Slide 51

Slide 51 text

$ jruby fiber_test.rb [7.603s][warning][os,thread] Attempt to protect stack guard pages failed (0x00007fc240a00000-0x00007fc240a04000). # # A fatal error has been detected by the Java Runtime Environment: # Native memory allocation (mprotect) failed to protect 16384 bytes for # memory to guard stack pages # # An error report file with more information is saved as: # /home/headius/work/jruby93/hs_err_pid75149.log # # If you would like to submit a bug report, please visit: # https://bugreport.java.com/bugreport/crash.jsp # Aborted (core dumped) 😩

Slide 52

Slide 52 text

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 53

Slide 53 text

No content

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

$ jruby -J--enable-preview fiber_test.rb 2.324123 0.880373 0.6916289999999999 0.73703 0.655856 🤩

Slide 56

Slide 56 text

C100k on JRuby? • See @ioquatix talks on async and falcon! • Just starting to add support for io-event, async-io in JRuby • Fiber scheduler and Buffer APIs available now • Great way to contribute!

Slide 57

Slide 57 text

Native Libraries

Slide 58

Slide 58 text

Ruby and C • Native libraries go hand-in-hand with Ruby • Many extensions written directly to internal APIs • More and more moving to FFI or Fiddle without C code • JRuby needs to support as much as possible • Extensions must be ported to Java (or Ruby) • FFI and Fiddle supported and strongly recommended

Slide 59

Slide 59 text

User Code JNR stub JNI call JNI impl libf f Target Library Java C/native

Slide 60

Slide 60 text

Project Panama: FFI for JVM • Foreign function interface (FFI) • With JVM help to make direct calls • Foreign memory API • JVM-assisted access, lifecycle • API extraction from C/++ headers • Save time setting up bindings

Slide 61

Slide 61 text

User Code Panama stub Target Library Java C/native

Slide 62

Slide 62 text

SQLite JDBC Adapter • Java DataBase Connectivity (JDBC) wrapper around SQLite • Used by JRuby for ActiveRecord, Sequel • Java Native Interface (JNI) currently, limits throughput • Proof-of concept Panama-based version working now • Early results: 2x performance

Slide 63

Slide 63 text

Prism Parser • Simple C library for parsing Ruby that we can share • JRuby already integrating it! • Nearly all nodes implemented, most code runs today • 20% faster startup • Using JNI/JNR now, will be faster with Panama

Slide 64

Slide 64 text

JRuby Future • JRuby 9.4 continues to stabilize • Moving toward maintenance mode • Lots of new JVM features to leverage • Very exciting time for (J)Rubyists! • Big announcement for the fi rst time today...

Slide 65

Slide 65 text

JRuby 10 is coming soon!

Slide 66

Slide 66 text

JRuby 10! • Major leap forward • Ruby 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 67

Slide 67 text

Help Build JRuby 10 • Implement Ruby 3.2, 3.3, 3.4 features (even in Ruby!) • Test libraries, applications and report issues • Triage reported bugs, con fi rm or reject or help fi x • We are standing by to work with you! • https://github.com/jruby/jruby

Slide 68

Slide 68 text

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