jruby on graal - the graal workshop · jruby review • ruby for the jvm • two-way integration...
TRANSCRIPT
![Page 1: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/1.jpg)
JRuby on GraalPerformance and Startup Experiments
![Page 2: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/2.jpg)
JRuby Review• Ruby for the JVM
• Two-way integration with Java, fitting into ecosystem
• We are a Ruby implementation, but also a JVM language
• Core classes largely written in Java
• Parts of core and most of standard library in Ruby
• Distribution like CRuby or as jars/wars, embedded into apps
• No support for CRuby extensions, on purpose
![Page 3: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/3.jpg)
JRuby Architecture
Ruby (.rb)
JIT
Java Instructions (java bytecode)
Ruby Instructions (IR)
parse
interpret
interpreter
interpret
C1 c
ompi
le
native code better native code
java bytecode interpreter
execute
C2 c
ompi
le
Java Virtual MachineJRuby Internals
deoptimize
![Page 4: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/4.jpg)
JRuby Challenges• Java bytecode is a narrow vocabulary
• InvokeDynamic helps but adds complexity
• Object boxes are too expensive
• Lambda-style code optimizes poorly
• Startup time, memory footprint are crucial for adoption
• Two FTEs barely keeps up with compatibility, user issues
![Page 5: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/5.jpg)
![Page 6: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/6.jpg)
JRuby and Graal
![Page 7: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/7.jpg)
History• Experimented with Maxine back in the day
• Collaborated with TruffleRuby early on
• Investigating JRuby performance on Graal
• Playing with compiler passes
• Studying compiler IR, assembly code for opportunities
![Page 8: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/8.jpg)
Today• JRuby on Graal straight-line performance
• Microbenchmarks up to small web services
• JRuby native with GraalVM
• Working POC
• Plans going forward
![Page 9: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/9.jpg)
Performance
![Page 10: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/10.jpg)
It's a Hard Problem• Heavy use of invokedynamic
• Method calls, constants, globals, instance variables, ...
• Limited specialization
• Object shaping, flattened arrays, frame elimination, splitting
• Looking for new opportunities
• e.g. "truly final" final fields
![Page 11: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/11.jpg)
General Notes• Java 8, Java 13, GraalVM 20
• Invokedynamic, fixnum caching options
• Java 13 using -XX:+UseParallelGC
• Iterations or requests per second (higher is better)
• Force compilation to JVM bytecode (no interpreted phase)
![Page 12: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/12.jpg)
Integer Loop
• Simple while loop from zero to 10M
• "nanobenchmark"
• Small method, simple integer math, conditional looping
![Page 13: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/13.jpg)
Integer Loop
0
6
12
18
24
Iterations per second
22.520.3
18
12.5
Java 8 Java 8 + Indy Java 13 + Indy Graal 20 + Indy
![Page 14: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/14.jpg)
Helping Graal• Make more state final
• Fewer loads, more constant propagation
• Avoid caching elidable objects
• Mixing real and virtual objects seems to cause problems
• Added a flag to disable Fixnum cache (like Integer.valueOf)
![Page 15: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/15.jpg)
Integer Loop
0
17.5
35
52.5
70
Iterations per second
67.1
22.520.31812.5
Java 8 Java 8 + Indy Java 13 + Indy Graal 20 + IndyGraal 20 + Indy - Fixnums
![Page 16: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/16.jpg)
Mandelbrot• Microbenchmark: one moderately-sized method
• Nearly all numeric computation
• Reasonable baseline for numeric algorithm performance
• Worst case for JRuby on most JVMs
• 100% boxed numerics
• Allocation rather than GC is the bottleneck
![Page 17: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/17.jpg)
Mandelbrot Optimizations
• Final references to Boolean objects, core classes
• Keep literal numerics as primitives
• Avoid caching Fixnum objects
![Page 18: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/18.jpg)
0
0.5
1
1.5
2
Java 8 Java 8 + Indy Java 13 + Indy Ruby 2.6.5
![Page 19: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/19.jpg)
0
3.5
7
10.5
14
Java 8 Java 8 + Indy Java 13 + Indy Graal 20 + IndyGraal 20 + Indy - Fixnums
![Page 20: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/20.jpg)
Optcarrot
• Nintendo Entertainment System emulator in pure Ruby
• Heavy use of simulated memory (integer arrays), dynamic dispatch
• Very little optimization work on JRuby side
![Page 21: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/21.jpg)
OptcarrotFirst 100 iterations
0
17.5
35
52.5
70
JRuby Java 13 JRuby Graal 20 Ruby 2.6.5 JIT
![Page 22: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/22.jpg)
OptcarrotLast 100 iterations
0
22.5
45
67.5
90
JRuby Java 13 JRuby Graal 20 Ruby 2.6.5 JIT
![Page 23: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/23.jpg)
Applications• Roda
• Microservice-style web framework
• Rails
• Heavily dependent on ActiveRecord performance
• CRuby vs JRuby, JRuby + Graal
![Page 24: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/24.jpg)
Roda• Small, well-supported service framework
• Many production users at large scales
• Very simple example with no database
• Benchmarking request routing mostly
• Good indicator of small app performance
![Page 25: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/25.jpg)
Setup
• CRuby: 8 processes
• JRuby: 8 threads
• Driver: wrk with 16 connections, 2 reactor threads
![Page 26: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/26.jpg)
Roda Full Concurrency
0
12500
25000
37500
50000
22,778
41,034 38,820 38,646 37,609 38,02242,304 41,731 39,172 41,786
15,556 15,275 14,533 12,872 14,093 13,593 14,141 14,764 12,236 13,998
CRuby JRuby Java 13 JRuby Graal 20 JRuby Java 13 Graal
![Page 27: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/27.jpg)
ActiveRecord Performance• Rails apps live and die by ActiveRecord
• Largest CPU consumer by far
• Heavy object churn, GC overhead
• Create, read, and update measurements
• CRuby 2.5.1 vs JRuby 9.2 on JDK11
![Page 28: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/28.jpg)
ActiveRecord Selects
time for 1000 selects, lower is better
0
0.075
0.15
0.225
0.3
CRuby 2.5 JRuby C2 JRuby Graal
binary boolean date datetime decimal float integerstring text time timestamp *
![Page 29: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/29.jpg)
JRuby + Graal• Clear wins for small, object-heavy benchmarks
• Larger applications are a mixed bag
• Need to dig deeper and see why
• Potential to be the fastest way to run JRuby
• Applicable to other languages and libraries on JVM
![Page 30: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/30.jpg)
Startup
![Page 31: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/31.jpg)
JRuby Architecture
Ruby (.rb)
JIT
Java Instructions (java bytecode)
Ruby Instructions (IR)
parse
interpret
interpreter
interpret
C1 c
ompi
le
native code better native code
java bytecode interpreter
execute
C2 c
ompi
le
Java Virtual MachineJRuby Internals
deoptimize
![Page 32: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/32.jpg)
total execution time (lower is better)
0
0.45
0.9
1.35
1.8
-e 1
0.0750.124
1.63
0.1
CRuby JRuby (JDK8) JRuby (10th iter) JRuby (50th iter)
![Page 33: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/33.jpg)
total execution time (lower is better)
0
1.25
2.5
3.75
5
gem --version gem list (~350 gems)
CRuby JRuby (JDK8) JRuby (10th iter)
![Page 34: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/34.jpg)
Startup Experiments
• Preboot or reuse JVM process
• Save parse results, compiled IR
• Precompile to native
![Page 35: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/35.jpg)
GraalVM Native Image• Compile all of JRuby to native (working POC)
• Build times in 2-3min range... not bad
• Many limitations
• No invokedynamic, limited reflection, no dynamic classloading, ...
• Eventual goal: fully native Ruby apps (no startup or warmup)
• Compile Ruby to bytecode, and then to native
• Good for tools, microservices
![Page 36: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/36.jpg)
total execution time (lower is better)
0
0.45
0.9
1.35
1.8
-e 1
0.117s
1.63s
0.1s
CRuby JRuby (JDK8) JRuby native
![Page 37: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/37.jpg)
Bytecode AOT Mode
• AOT mode: No indy at all
• A bit more bytecode generated
• Only direct method handles or LambdaMetaFactory objects
• Cold bytecodes reduced vs normal precompile
![Page 38: JRuby on Graal - The Graal Workshop · JRuby Review • Ruby for the JVM • Two-way integration with Java, fitting into ecosystem • We are a Ruby implementation, but also a JVM](https://reader035.vdocument.in/reader035/viewer/2022070908/5f8988fc17a20258092ed082/html5/thumbnails/38.jpg)
Next Steps• Compile Ruby app + library sources to native
• Needed bytecode AOT to proceed
• Static optimizations
• Remove unneeded parts of JRuby
• Probably limited to small services, command line tools
• libjruby?