fosdem 2016 - optimizing jruby · jruby 9000 optimizing above the jvm. me ... jruby 9000 •...

58
JRuby 9000 Optimizing Above the JVM

Upload: others

Post on 15-Jul-2020

21 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

JRuby 9000Optimizing Above the JVM

Page 2: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Me

• Charles Oliver Nutter (@headius)

• Red Hat

• Based in Minneapolis, Minnesota

• Ten years working on JRuby (uff da!)

Page 3: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Ruby Challenges

• Dynamic dispatch for most things

• Dynamic possibly-mutating constants

• Fixnum to Bignum promotion

• Literals for arrays, hashes: [a, b, c].sort[1]

• Stack access via closures, bindings

• Rich inheritance model

Page 4: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

module SayHello def say_hello "Hello, " + to_s endendclass Foo include SayHello def initialize @my_data = {bar: 'baz', quux: 'widget'} end def to_s @my_data.map do |k,v| "#{k} = #{v}" end.join(', ') endendFoo.new.say_hello # => "Hello, bar = baz, quux = widget"

Page 5: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

More Challenges

• "Everything's an object"

• Tracing and debugging APIs

• Pervasive use of closures

• Mutable literal strings

Page 6: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

JRuby 9000

• Optimizable intermediate representation

• Mixed mode runtime (now with tiers!)

• Lazy JIT to JVM bytecode

• byte[] strings and regular expressions

• Lots of native integration via FFI

• 9.0.5.0 is current

Page 7: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Intermediate Representation

• AST to semantic representation

• Traditional compiler design

• Register machine

Page 8: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

LexicalAnalysisParsing

SemanticAnalysis

Optimization

Bytecode GenerationInterpret

AST

IR Instructions

CFG DFG ...

JRuby 1.7.x

9000+

BytecodeGenerationInterpret

Page 9: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)2 b = recv_pre_reqd_arg(1)3 %block = recv_closure4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Register-based

3 address format

IR InstructionsSemanticAnalysis

Page 10: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

-Xir.passes=LocalOptimizationPass, DeadCodeElimination

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)2 b = recv_pre_reqd_arg(1)3 %block = recv_closure4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Optimization

Page 11: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

-Xir.passes=LocalOptimizationPass, DeadCodeElimination

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)2 b = recv_pre_reqd_arg(1)3 %block = recv_closure4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Optimization

Page 12: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

-Xir.passes=LocalOptimizationPass, DeadCodeElimination

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)2 b = recv_pre_reqd_arg(1)3 %block = recv_closure4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Optimization

Page 13: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 14: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 15: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll5 line_num(1)6 c = 17 line_num(2)8 %v_0 = call(:+, a, [c])9 d = copy(%v_0)10 return(%v_0)

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 16: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll5 line_num(1)6 c = 7 line_num(2)8 %v_0 = call(:+, a, [ ])9 d = copy(%v_0)10 return(%v_0)

1

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 17: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def foo(a, b) c = 1 d = a + cend

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll5 line_num(1)7 line_num(2)8 %v_0 = call(:+, a, [1])9 d = copy(%v_0)10 return(%v_0)

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 18: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll5 line_num(1)7 line_num(2)8 %v_0 = call(:+, a, [1])9 d = copy(%v_0)10 return(%v_0)

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 19: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

0 check_arity(2, 0, -1)1 a = recv_pre_reqd_arg(0)4 thread_poll7 line_num(2)8 %v_0 = call(:+, a, [1])9 d = copy(%v_0)10 return(%v_0)

Optimization -Xir.passes=LocalOptimizationPass, DeadCodeElimination

Page 20: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Tiers!

• Tier 1: Simple interpreter (no passes run)

• Tier 2: Full interpreter (static optimization)

• Tier 3: Full interpreter (profiled optz)

• Tier 4: JVM bytecode (static)

• Tier 5: JVM bytecode (profiled)

• Tiers 6+: Whatever JVM does from there

Page 21: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Why Not Truffle?

• Startup and memory use are worse

• No integration with other JVM langs yet

• We still want to target JVM

• It's not ready yet!

Page 22: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Current Optimizations

Page 23: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Block Jitting

• JRuby 1.7 only jitted methods

• Not free-standing procs/lambdas

• Not define_method blocks

• Easier to do now with 9000's IR

• Blocks JIT as of 9.0.4.0

Page 24: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

define_method

Convenient for metaprogramming,but blocks have more overhead than methods.

define_method(:add) do |a, b| a + b end

names.each do |name| define_method(name) { send :"do_#{name}" } end

Page 25: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Optimizing define_method

• Noncapturing

• Treat as method in compiler

• Ignore surrounding scope

• Capturing (future work)

• Lift read-only variables as constant

Page 26: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Getting Better!

0k iters/s

1000k iters/s

2000k iters/s

3000k iters/s

4000k iters/s

def define_method define_method w/ capture

MRI JRuby 9.0.1.0 JRuby 9.0.4.0

Page 27: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Low-cost Exceptions

• Backtrace cost is VERY high on JVM

• Lots of work to construct

• Exceptions frequently ignored

• ...or used as flow control (shame!)

• If ignored, backtrace is not needed!

Page 28: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Postfix Antipattern

foo rescue nil

Exception raisedStandardError rescued

Exception ignored

Result is simple expression, so exception is never visible.

Page 29: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

csv.rb Converters

Converters = { integer: lambda { |f| Integer(f) rescue f }, float: lambda { |f| Float(f) rescue f }, ...

All trivial rescues, no traces needed.

Page 30: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Strategy

• Inspect rescue block

• If simple expression...

• Thread-local requiresBacktrace = false

• Backtrace generation short circuited

• Reset to true on exit or nontrivial rescue

Page 31: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

public class ToggleBacktraceInstr extends NoOperandInstr { private final boolean requiresBacktrace; public ToggleBacktraceInstr(boolean requiresBacktrace) { super(Operation.TOGGLE_BACKTRACE); this.requiresBacktrace = requiresBacktrace; }

Page 32: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Simple rescue Improvement

0

150000

300000

450000

600000

Iters/second

524,475

10,700

Page 33: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Much Better!

1

10

100

1000

10000

100000

1000000

Iters/second

524,475

10,700

Page 34: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Work In Progress

Page 35: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Object Shaping

• Ruby instance vars allocated dynamically

• JRuby currently grows an array

• We have code to specialize as fields

• Working, tested

• Probably next release

Page 36: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Inlining

• 900 pound gorilla of optimization

• shove method/closure back to callsite

• specialize closure-receiving methods

• eliminate call protocol

• We know Ruby better than the JVM

Page 37: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

But... JVM?

• JVM will inline for us, but...

• only if we use invokedynamic

• and the code isn't too big

• and there's no polymorphic code

• and we're not yielding to a closure

• and it feels like it today

Page 38: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Today’s Inliner

def decrement_one(i) i - 1end

i = 1_000_000while i > 0 i = decrement_one(i)end

def decrement_one(i) i - 1end

i = 1_000_000while i < 0 if guard_same? self i = i - 1 else i = decrement_one(i) endend

Page 39: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Today’s Inliner

def decrement_one(i) i - 1end

i = 1_000_000while i > 0 i = decrement_one(i)end

def decrement_one(i) i - 1end

i = 1_000_000while i < 0 if guard_same? self i = i - 1 else i = decrement_one(i) endend

Page 40: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Today’s Inliner

def decrement_one(i) i - 1end

i = 1_000_000while i > 0 i = decrement_one(i)end

def decrement_one(i) i - 1end

i = 1_000_000while i < 0 if guard_same? self i = i - 1 else i = decrement_one(i) endend

Page 41: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Today’s Inliner

def decrement_one(i) i - 1end

i = 1_000_000while i > 0 i = decrement_one(i)end

def decrement_one(i) i - 1end

i = 1_000_000while i < 0 if guard_same? self i = i - 1 else i = decrement_one(i) endend

Page 42: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Profiling

• You can't inline if you can't profile!

• For each call site record call info

• Which method(s) called

• How frequently

• Inline most frequently-called method

Page 43: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Inlining a Closuredef small_loop(i) k = 10 while k > 0 k = yield(k) end i - 1end

def big_loop(i) i = 100_000 while true i = small_loop(i) { |j| j - 1 } return 0 if i < 0 endend

900.times { |i| big_loop i }

hot & monomorphic

Like an Array#each

May see many blocksJVM will not inline this

Page 44: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Inlining FTW!

0

15

30

45

60

Time in seconds

14.1

56.9

Page 45: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Profiling

• <2% overhead (to be reduced more)

• Working* (interpreter AND JIT)

• Feeds directly into inlining

• Deopt coming soon

* Fragile and buggy!

Page 46: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Interpreter FTW!

• Deopt is much simpler with interpreter

• Collect local vars, instruction index

• Raise exception to interpreter, keep going

• Much cheaper than resuming bytecode

Page 47: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Numeric Specialization

• "Unboxing"

• Ruby: everything's an object

• Tagged pointer for Fixnum, Float

• JVM: references OR primitives

• Need to optimize numerics as primitive

Page 48: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

But... EA?

• Hotspot will eliminate boxes if...

• All code inlines

• No branches in the code

• Dynamic calls have type guards

• EA does not work for us!

Page 49: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def looper(n) i = 0 while i < n do_something(i) i += 1 endend

def looper(long n) long i = 0 while i < n do_something(i) i += 1 endend

Specialize n, i to long

def looper(n) i = 0 while i < n do_something(i) i += 1 endend

Deopt to object version if n or i + 1 is not Fixnum

Page 50: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Unboxing Today

• Working prototype

• No deopt

• No type guards

• No overflow check for Fixnum/Bignum

Page 51: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Rendering

* * * * * *** ***** ***** *** * ********* ************* *************** ********************* ********************* ******************* ******************* ******************* ******************* *********************** ******************* ******************* ********************* ******************* ******************* ***************** *************** ************* ********* * *************** *********************** * ************************* * ***************************** * ******************************* * ********************************* *********************************** *************************************** *** ***************************************** *** ************************************************* *********************************************** ********************************************* ********************************************* *********************************************** *********************************************** *************************************************** ************************************************* ************************************************* *************************************************** *************************************************** * *************************************************** * ***** *************************************************** ***** ****** *************************************************** ****** ******* *************************************************** ******* *********************************************************************** ********* *************************************************** ********* ****** *************************************************** ****** ***** *************************************************** ***** *************************************************** *************************************************** *************************************************** *************************************************** ************************************************* ************************************************* *************************************************** *********************************************** *********************************************** ******************************************* ***************************************** ********************************************* **** ****************** ****************** **** *** **************** **************** *** * ************** ************** * *********** *********** ** ***** ***** ** * * * * 0.520000 0.020000 0.540000 ( 0.388744)

Page 52: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

def iterate(x,y) cr = y-0.5 ci = x zi = 0.0 zr = 0.0 i = 0 bailout = 16.0 max_iterations = 1000 while true i += 1 temp = zr * zi zr2 = zr * zr zi2 = zi * zi zr = zr2 - zi2 + cr zi = temp + temp + ci return i if (zi2 + zr2 > bailout) return 0 if (i > max_iterations) endend

Page 53: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Mandelbrot performance

0

0.35

0.7

1.05

1.4

JRuby JRuby + truffle

Page 54: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Mandelbrot performance

0

0.075

0.15

0.225

0.3

JRuby JRuby + truffle

Page 55: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Mandelbrot performance

0

0.075

0.15

0.225

0.3

JRuby JRuby + truffle JRuby on Graal

Page 56: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Mandelbrot performance

0

0.035

0.07

0.105

0.14

JRuby + truffle JRuby on Graal JRuby unbox

Page 57: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

When?

• Object shape should be in 9.1

• Profiling, inlining mostly need testing

• Specialization needs guards, deopt

• Probably landing in next couple months

Page 58: FOSDEM 2016 - Optimizing JRuby · JRuby 9000 Optimizing Above the JVM. Me ... JRuby 9000 • Optimizable ... FOSDEM 2016 - Optimizing JRuby.key Created Date: 2/8/2016 2:47:18 PM

Thank You

• Charles Oliver Nutter

• @headius

[email protected]