3 The following is intended to provide some insight into a line of research in Oracle Labs. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described in connection with any Oracle product or service remains at the sole discretion of Oracle. Any views expressed in this presentation are my own and do not necessarily reflect the views of Oracle.
6 “Write Your Own Language” Prototype a new language Parser and language work to build syntax tree (AST), AST Interpreter Write a “real” VM In C/C++, still using AST interpreter, spend a lot of time implementing runtime system, GC, … People start using it Define a bytecode format and write bytecode interpreter People complain about performance Write a JIT compiler Improve the garbage collector Performance is still bad Prototype a new language in Java Parser and language work to build syntax tree (AST) Execute using AST interpreter People start using it And it is already fast Current situation How it should be
8 System Structure Low-footprint VM, also suitable for embedding Common API between language implementation and optimization system Language agnostic dynamic compiler Your language here! Integrate with Java applications Substrate VM Truffle Graal Ruby JavaScript Python R Graal VM …
13 Ruby Prototype: Completeness § RubySpec § A library of executable assertions that covers the language, core library and standard library § This is the defacto Ruby spec § Gives us a quantifiable result for how much of Ruby we implement correctly Over 45% of RubySpec
15 Completeness: Informally Charles Nutter: ‘So You Want to Optimize Ruby’ http://blog.headius.com/2012/10/so-you-want-to-optimize-ruby.html Language Feature Implemented Notes Fixnum to Bignum promotion ✓ Support for floating point ✓ Closures ✓ Bindings and eval ✓ callcc and Continuation ✓ Very limited support, the same as JRuby Fibers ✓ Slightly limited support, the same as JRuby Frame local variables ✓ C extensions Ruby 1.9 encoding ✓ Garbage collection ✓ Concurrency and parallelism ✓ We currently use a GIL Tracing and debugging ✓ ObjectSpace ✓ Method invalidation ✓ Constant invalidation ✓ Ruby on Rails
18 Ahead-of-Time Compilation Static Analysis Substrate VM Execution Model Substrate VM Java Application JDK Reachable methods, fields, and classes Initial Heap Machine Code OS All Java classes from application, JDK, and Substrate VM Application running without compilation or class loading
22 Why is Ruby Slow? -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division
23 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division + - / b sqrt * ... 2 a
24 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division + - / b sqrt * ... 2 a
25 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division + - / b sqrt * ... 2 a
26 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division + - / b sqrt * ... 2 a
27 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division + - / b sqrt * ... 2 a
28 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division + - / b sqrt * ... 2 a + - / b * ... 2 a sqrt
29 Improving Performance Using Truffle -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division execute b check that b is a Float check that the negate method in Float has not changed calculate negation check the result of that is a Float execute b check that b is a Float check that the power method in Float has not changed calculate power check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float execute c check that c is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt check the result of that is a Float execute a check that a is a Float check that the multiply method in Float has not changed calculate multiplication check the result of that is a Float check that the division method in Float has not changed calculate division
30 Improving Performance Using Graal -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division
31 Improving Performance Using Graal -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division class Float ⚑ modified? module Math ⚑ modified?
32 Improving Performance Using Graal -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division class Float ⚑ modified? module Math ⚑ modified?
33 Improving Performance Using Graal -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division class Float ⚑ modified? module Math ⚑ modified? java object InstalledCode .invalidate()
34 Improving Performance Using Graal -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division class Float ⚑ modified? module Math ⚑ modified? java object InstalledCode .invalidate()
36 Improving Performance Using Graal -b + (Math.sqrt(b**2 - 4*a*c)) / 2*a execute b calculate negation execute b calculate power execute a calculate multiplication execute c calculate multiplication calculate sqrt execute a calculate multiplication calculate division execute b check that the negate method in Float has not changed calculate negation execute b check that the power method in Float has not changed calculate power execute a check that the multiply method in Float has not changed calculate multiplication execute c check that the multiply method in Float has not changed calculate multiplication check that Math has not changed check that the sqrt method in Math has not changed calculate sqrt execute a check that the multiply method in Float has not changed calculate multiplication check that the division method in Float has not changed calculate division
40 Simplicity § One intern working for five months on the Ruby implementation § New to Truffle, Graal and Ruby § Written using Eclipse § Debugged as a normal Java program using the server compiler § Run using Graal for testing and performance numbers § No mention in the implementation of bytecode, classloaders, assembly, system calls, OSR § One very minor use of Unsafe, one very minor use of reflection
41 Oracle Labs Laurent Daynès Michael Haupt Peter Kessler Christos Kotselidis David Leibs Roland Schatz Chris Seaton Doug Simon Michael Van De Vanter Christian Wimmer Christian Wirth Mario Wolczko Thomas Würthinger Laura Hill (Manager) JKU Linz Gilles Duboscq Matthias Grimmer Christian Häubl Josef Haider Christian Humer Christian Huber Manuel Rigger Lukas Stadler Bernhard Urban Andreas Wöß Prof. Hanspeter Mössenböck Acknowledgments Oracle Labs Interns Danilo Ansaloni Daniele Bonetta Shams Imam Stephen Kell Helena Kotthaus Gregor Richards Rifat Shariyar Codrut Stancu Wei Zhang Purdue University Tomas Kalibera" Floreal Morandat" Petr Maj Prof. Jan Vitek University of California, Irvine University of Dortmund
44 Truffle Approach (Details) U U U U U I I I G G I I I G G AST Rewriting for Profiling Feedback AST Interpreter Rewritten Nodes AST Interpreter Uninitialized Nodes Compilation using Partial Evaluation Compiled Code Node Transitions S U I D G Uninitialized Integer Generic Double String I I I G G I I I G G Deoptimization to AST Interpreter D I D G G D I D G G AST Rewriting to Update Profiling Feedback Recompilation using Partial Evaluation
45 System Structure (Details) Guest Language Application OS AOT Optimization: using Graal for static analysis and AOT compilation Language Parser AST Interpreter Guest Language Implementation Truffle API Framework for Node Rewriting Truffle Optimizer Partial Evaluation using Graal VM Runtime Services Garbage Collector Graal Compiler Stack Walking Deoptimization Hosted on any Java VM Hosted on Graal VM (slow, for guest language development and debugging only) (fast, for integration of guest language code with existing Java applications)