SlideShare a Scribd company logo
1 of 120
HIGH PERFORMANCE
       RUBY
Hiya

• Charles Oliver Nutter
• headius@headius.com
• @headius
• JVM language guy at Red Hat (JBoss)
Performance?
• Writing code
 • Man hours more expensive than CPU
    hours
 • Developer contentedness
• Running code
 • Straight line
High Performance?

• Faster than...
 • ...other Ruby impls?
 • ...other language runtimes?
 • ...unmanaged languages, like C?
 • ...you need it to be?
“Fast Enough”

• 1.8.7 was fast enough
• 1.9.3 is fast enough
• Unless it’s not fast enough
 • Does it matter?
Performance Wall

• Move to a different runtime
• Move to a different language
 • ...in whole or part
If you’re not writing perf-
  sensitive code in Ruby,
you’re giving up too easily.
Native Extensions

• Not universally bad
• Just bad in MRI
 • Invasive
 • Pointers
 • Few guarantees
What We Want

• Faster execution
• Better GC
• Parallel execution
• Big data
What We Can’t Have

• Faster execution
• Better GC
• Parallel execution
• Big data
Different Approach

• Build our own runtime?
 • YARV, Rubinius, MacRuby
• Use an existing runtime?
 • JRuby, MagLev, MacRuby, IronRuby
Build or Buy

• Making a new VM is “easy”
• Making it competitive is really hard
• I mean really, really, really hard
JVM
• 15+ years of engineering by whole teams
• FOSS
• Fastest VM available
• Best GCs available
• Full parallel threading with guarantees
• Broad platform support
But Java is Slow!
• Java is very, very fast
 • Literally, C fast in many cases
• Java applications can be slow
 • Oh hey, just like Ruby?
• The way you write code is more important
  than the language you use.
JRuby

• Java (and Ruby) impl of Ruby on JVM
• Same memory, threading model
• JRuby JITs to JVM bytecode
• End of story, right?
Long, Hard Road

• Interpreter optimization
• JVM bytecode compiler
• Optimizing core class methods
• Lather, rinse, and repeat
Align with JVM

• Individual arguments on call stack
• JVM local variables
• Avoid artificial framing
• Avoid inter-call goo
• Eliminate unnecessary work
Unnecessary Work
• Modules are maps
 • Name to method
 • Name to constant
 • Name to class var
• Instance variables as maps
• Wasted cycles without caching
Method Lookup
• Inside a class/module
 • Current class’s methods (a map)
 • Methods retrieved from class + ancestors
 • Serial or switch indicates staleness
 • Weak list of child classes
• Class mutation cascades down hierarchy
Thing



                 Person           Place



obj.to_s   Rubyist        Other
Method lookups go up-hierarchy            Thing



                                 Person           Place



       obj.to_s         Rubyist           Other
to_s
Method lookups go up-hierarchy            Thing



                                 Person            Place



       obj.to_s         Rubyist           Other
to_s
Method lookups go up-hierarchy            Thing

 Lookup target caches result

                                 Person            Place



       obj.to_s          Rubyist          Other
Method lookups go up-hierarchy             Thing

 Lookup target caches result

                                  Person           Place


                               to_s
       obj.to_s          Rubyist           Other
Method lookups go up-hierarchy             Thing

 Lookup target caches result
Modification cascades down         Person           Place


                               to_s
       obj.to_s          Rubyist           Other
Method lookups go up-hierarchy             Thing
                                             to_s

 Lookup target caches result
Modification cascades down         Person            Place


                               to_s
       obj.to_s          Rubyist           Other
Constant Lookup

• Cache at lookup site
• Global serial/switch indicates staleness
 • Complexities of lookup, etc
 • Joy of Ruby interfering with Joy of Opto
• Modifying constants triggers invalidation
Instance Vars

• Class holds a table of offsets
• Object holds array of values
• Call site caches offset plus class ID
• Same class, no lookup cost
 • Can be polymorphically chained
Optimizing Ruby

• Make calls fast
• Make constants free
• Make instance variables cheap
• Make closures lightweight
 • TODO
What is
invokedynamic?
Invoke?
Invoke?
That’s one use, but there are many others
Dynamic?
Dynamic?
Dynamic typing is a common reason,
    but there are many others
JVM 101
JVM 101
200 opcodes
JVM 101
       200 opcodes
Ten (or 16) “data endpoints”
JVM 101
                   200 opcodes
            Ten (or 16) “data endpoints”
   Invocation
 invokevirtual
invokeinterface
 invokestatic
 invokespecial
JVM 101
                   200 opcodes
            Ten (or 16) “data endpoints”
   Invocation       Field Access
 invokevirtual       getfield
invokeinterface      setfield
 invokestatic        getstatic
 invokespecial       setstatic
JVM 101
                   200 opcodes
            Ten (or 16) “data endpoints”
   Invocation       Field Access     Array Access
 invokevirtual       getfield          *aload
invokeinterface      setfield          *astore
 invokestatic        getstatic     b,s,c,i,l,d,f,a
 invokespecial       setstatic
JVM 101
                   200 opcodes
            Ten (or 16) “data endpoints”
   Invocation       Field Access      Array Access
 invokevirtual       getfield          *aload
invokeinterface      setfield          *astore
 invokestatic        getstatic     b,s,c,i,l,d,f,a
 invokespecial       setstatic

   All Java code revolves around these endpoints
  Remaining ops are stack, local vars, flow control
    allocation, and math/boolean/bit operations
JVM
Opcodes
JVM
              Opcodes
 Invocation       Field Access   Array Access
 invokevirtual      getfield
                                     *aload
invokeinterface     setfield
                                     *astore
 invokestatic       getstatic
                                 b,s,c,i,l,d,f,a
 invokespecial      setstatic
JVM
              Opcodes
 Invocation       Field Access   Array Access
 invokevirtual      getfield
                                     *aload
invokeinterface     setfield
                                     *astore
 invokestatic       getstatic
                                 b,s,c,i,l,d,f,a
 invokespecial      setstatic




    Stack                            Local Vars
                  Flow Control


                                  Allocation
 Boolean and Numeric
JVM
              Opcodes
 Invocation       Field Access   Array Access
 invokevirtual      getfield
                                     *aload
invokeinterface     setfield
                                     *astore
 invokestatic       getstatic
                                 b,s,c,i,l,d,f,a
 invokespecial      setstatic




    Stack                            Local Vars
                  Flow Control


                                  Allocation
 Boolean and Numeric
JVM
              Opcodes
 Invocation       Field Access   Array Access
 invokevirtual      getfield
                                     *aload
invokeinterface     setfield
                                     *astore
 invokestatic       getstatic
                                 b,s,c,i,l,d,f,a
 invokespecial      setstatic




    Stack                            Local Vars
                  Flow Control


                                  Allocation
 Boolean and Numeric
In Detail

• JRuby generates code with indy calls
• JVM at first call asks JRuby what to do
• JRuby provides function pointers to code
• Pointers include guards, invalidation logic
• JRuby and JVM cooperate on optimizing
invokedynamic bytecode
invokedynamic bytecode




bo
  ot
     stra
         p
             m
              et
                ho
                  d
invokedynamic bytecode




bo
  ot
     stra
         p
             m
              et
                ho
                  d             method handles
invokedynamic bytecode

                                  target method



bo
  ot
     stra
         p
             m
              et
                ho
                  d             method handles
invokedynamic bytecode

                                  target method



bo
  ot
     stra
         p
             m
              et
                ho
                  d             method handles
invokedynamic bytecode

                                  target method



bo
  ot
     stra
         p
             m
              et
                ho
                  d             method handles
Dynamic Invocation
                  Target
                  Object

                         associated with
obj.foo()   JVM
                  Method
                   Table
                  def foo ...

                  def bar ...
Dynamic Invocation
VM Operations
                      Target
                      Object

                             associated with
   obj.foo()    JVM
                      Method
                       Table
   Call Site          def foo ...

                      def bar ...
Dynamic Invocation
VM Operations
                      Target
                      Object

                             associated with
   obj.foo()    JVM
                      Method
                       Table
   Call Site          def foo ...

                      def bar ...
Dynamic Invocation
VM Operations
  Method Lookup                 Target
                                Object

                                       associated with
   obj.foo()       JVM
                                Method
                                 Table
   Call Site                    def foo ...
                  def foo ...
                                def bar ...
Dynamic Invocation
VM Operations
  Method Lookup                 Target
     Branch
                                Object

                                       associated with
   obj.foo()       JVM
                                Method
                                 Table
   Call Site                    def foo ...
                  def foo ...
                                def bar ...
Dynamic Invocation
VM Operations
  Method Lookup              Target
     Branch
  Method Cache               Object

                                    associated with
   obj.foo()           JVM
         def foo ...
                             Method
                              Table
   Call Site                 def foo ...

                             def bar ...
Constants



               JVM       Constant
MY_CONST
                         Lookup

 Call Site
Constants
VM Operations



                  JVM       Constant
 MY_CONST
                            Lookup

   Call Site
Constants
VM Operations



                  JVM       Constant
 MY_CONST
                            Lookup

   Call Site
Constants
VM Operations
  Lookup Value




                   JVM        Constant
 MY_CONST
                         value Lookup

   Call Site
Constants
VM Operations
   Lookup Value
 Bind Permanently



                       JVM       Constant
 MY_CONST
             value               Lookup

   Call Site
Instance Variables
                  Target
                  Object

                        associated with
@bar     JVM
                  Offset
                  Table
                  “@foo” => 0
                  “@bar” => 1
Instance Variables
VM Operations
                        Target
                        Object

                              associated with
    @bar        JVM
                        Offset
                        Table
  Access Site           “@foo” => 0
                        “@bar” => 1
Instance Variables
VM Operations
Instance Var Lookup         Target
                            Object

                                  associated with
     @bar             JVM
                            Offset
                            Table
  Access Site               “@foo” => 0
                            “@bar” => 1
Instance Variables
VM Operations
Instance Var Lookup         Target
    Offset Cache
                            Object

                                  associated with
     @bar             JVM
            1
                            Offset
                            Table
  Access Site               “@foo” => 0
                            “@bar” => 1
Instance Variables
VM Operations
Instance Var Lookup         Target
    Offset Cache
   Access Object            Object

                                  associated with
     @bar             JVM
            1
                            Offset
                            Table
  Access Site               “@foo” => 0
                            “@bar” => 1
Instance Variables
VM Operations
Instance Var Lookup         Target
    Offset Cache
   Access Object            Object

                                  associated with
     @bar             JVM
            1
                            Offset
                            Table
  Access Site               “@foo” => 0
                            “@bar” => 1
InvokeDynamic lets
JRuby teach the JVM
   how Ruby works
How Do We Know
  We’ve Succeeded?

• Benchmarking
• Monitoring
• User reports
Benchmarking is Hard

• Runtimes may improve over time
• Optimizer may eliminate useless code
• Small systems are completely different
• Know how your runtime optimizes!
bench_empty_method
def foo; self; end

i = 0
while i < 10_000_000
  foo; foo; foo; foo; foo
  i += 1
end
Ruby 1.9.3   JRuby      JRuby + indy

4s



3s



2s



1s



0s
                     ZOMG
                            40X FA
                                      STER!
Observations
One slow runtime
screws up the table
...do comparisons as
ratios against a norm
JRuby calls empty
methods really fast!!!
InvokeDynamic does
not do much for us?
Ruby 1.9.3   JRuby   JRuby + indy

4s



3s



2s



1s



0s
JVM Opto 101
• JITs code bodies after 10k calls
 • No 10k calls, no JIT (generally)
• Inlines up to two targets
• Optimistic
 • Early decisions may be wrong
 • Small code looks drastically different
SMALL CODE IS
DIFFERENT THAN
  LARGE CODE
Inlining

• Call site in method A and method B match
• JVM treats them as though B lived in A
 • No call overhead
 • Variables visible across call boundary
 • More complete view for optimization
Optimistic

• Say we have a system...
• The only method dynamically called is “foo”
• All logic for dyncall revolves around “foo”
• Hotspot thinks all dyncalls will be “foo”
bench_empty_method2
def foo; self; end
def bar1; self; end
def bar2; self; end

i = 0
while i < 10_000_000
  bar1; bar1; bar1; bar1; bar1
  bar2; bar2; bar2; bar2; bar2
  i += 1
end
...
bench1   bench2   bench1 + indy   bench2 + indy

  0.7s



0.525s



 0.35s



0.175s



   0s
bench1 + rbx    bench2 + rbx   bench1 + indy
       bench2 + indy
0.4s



0.3s



0.2s



0.1s



 0s
What Happened?

• An unrelated change slowed our bench?
• Not really unrelated
 • Hotspot optimizes early loop first
 • Later loop is different...calls “foo”
 • Assumptions change, perf looks different
Benchmarking is
       Not Enough
• Need to monitor runtime optimization
 • JIT compilation
 • Inlining
 • Eventual native code (x86 ASM)
• Fun?
1711   4 %    bench_empty_method::block_0$RUBY$__file__ @ 56 (171 bytes)
             @ 59 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot)
              @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot)
                @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot)
                 @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
                @ 16 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
                 @ 1 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot)
              @ 12 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
              @ 29 java.lang.invoke.MethodHandle::invokeExact (35 bytes) inline (hot)
                @ 5 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot)
                 @ 3 org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass (17 bytes)   inline (hot)
                  @ 5 org.jruby.RubyBasicObject::getMetaClass (5 bytes) inline (hot)
                @ 14 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
                @ 31 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
                 @ 6 bench_empty_method::method__0$RUBY$foo (2 bytes) inline (hot)
             @ 68 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot)
              @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot)
                @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot)
                 @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
1711   4 %    bench_empty_method::block_0$RUBY$__file__ @ 56 (171 bytes)
             @ 59 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot)
              @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot)
                @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot)
                 @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
                @ 16 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
                 @ 1 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot)
              @ 12 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
              @ 29 java.lang.invoke.MethodHandle::invokeExact (35 bytes) inline (hot)
                @ 5 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot)
                 @ 3 org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass (17 bytes)   inline (hot)
                  @ 5 org.jruby.RubyBasicObject::getMetaClass (5 bytes) inline (hot)
                @ 14 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
                @ 31 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
                 @ 6 bench_empty_method::method__0$RUBY$foo (2 bytes) inline (hot)
             @ 68 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot)
              @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot)
                @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot)
                 @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
1711   4 %    bench_empty_method::block_0$RUBY$__file__ @ 56 (171 bytes)
             @ 59 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot)
              @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot)
                @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot)
                 @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
                @ 16 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
                 @ 1 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot)
              @ 12 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
              @ 29 java.lang.invoke.MethodHandle::invokeExact (35 bytes) inline (hot)
                @ 5 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot)
                 @ 3 org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass (17 bytes)   inline (hot)
                  @ 5 org.jruby.RubyBasicObject::getMetaClass (5 bytes) inline (hot)
                @ 14 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
                @ 31 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot)
                 @ 6 bench_empty_method::method__0$RUBY$foo (2 bytes) inline (hot)
             @ 68 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot)
              @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot)
                @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot)
                 @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
Decoding compiled method 0x000000010549d7d0:
Code:
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'method__0$RUBY$foo' '(Lbench_empty_method;Lorg/jruby/runtime/ThreadContext;Lorg/jruby/
runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;' in
'bench_empty_method'
  # parm0:    rsi:rsi = 'bench_empty_method'
  # parm1:    rdx:rdx = 'org/jruby/runtime/ThreadContext'
  # parm2:    rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject'
  # parm3:    r8:r8    = 'org/jruby/runtime/Block'
  #         [sp+0x20] (sp of caller)
  0x000000010549d900: sub    $0x18,%rsp
  0x000000010549d907: mov    %rbp,0x10(%rsp)    ;*synchronization entry
                                  ; - bench_empty_method::method__0$RUBY$foo@-1 (line 3)
  0x000000010549d90c: mov    %rcx,%rax
  0x000000010549d90f: add    $0x10,%rsp
  0x000000010549d913: pop    %rbp
  0x000000010549d914: test %eax,-0xe9f91a(%rip)         # 0x00000001045fe000
                                  ; {poll_return}
  0x000000010549d91a: retq
Decoding compiled method 0x000000010549d7d0:
Code:
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'method__0$RUBY$foo' '(Lbench_empty_method;Lorg/jruby/runtime/ThreadContext;Lorg/jruby/
runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;' in
'bench_empty_method'
  # parm0:    rsi:rsi = 'bench_empty_method'
  # parm1:    rdx:rdx = 'org/jruby/runtime/ThreadContext'
  # parm2:    rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject'
  # parm3:    r8:r8    = 'org/jruby/runtime/Block'
  #         [sp+0x20] (sp of caller)
  0x000000010549d900: sub    $0x18,%rsp
  0x000000010549d907: mov    %rbp,0x10(%rsp)    ;*synchronization entry
                                  ; - bench_empty_method::method__0$RUBY$foo@-1 (line 3)
  0x000000010549d90c: mov    %rcx,%rax
  0x000000010549d90f: add    $0x10,%rsp
  0x000000010549d913: pop    %rbp
  0x000000010549d914: test %eax,-0xe9f91a(%rip)         # 0x00000001045fe000
                                  ; {poll_return}
  0x000000010549d91a: retq
Decoding compiled method 0x000000010549d7d0:
Code:
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'method__0$RUBY$foo' '(Lbench_empty_method;Lorg/jruby/runtime/ThreadContext;Lorg/jruby/
runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;' in
'bench_empty_method'
  # parm0:    rsi:rsi = 'bench_empty_method'
  # parm1:    rdx:rdx = 'org/jruby/runtime/ThreadContext'
  # parm2:    rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject'
  # parm3:    r8:r8    = 'org/jruby/runtime/Block'
  #         [sp+0x20] (sp of caller)
  0x000000010549d900: sub    $0x18,%rsp
  0x000000010549d907: mov    %rbp,0x10(%rsp)    ;*synchronization entry
                                  ; - bench_empty_method::method__0$RUBY$foo@-1 (line 3)
  0x000000010549d90c: mov    %rcx,%rax
  0x000000010549d90f: add    $0x10,%rsp
  0x000000010549d913: pop    %rbp
  0x000000010549d914: test %eax,-0xe9f91a(%rip)         # 0x00000001045fe000
                                  ; {poll_return}
  0x000000010549d91a: retq
bench_empty_method3
def invoker1
  i = 0
  while i < 1000
    foo; foo; foo; foo; foo
    i+=1
  end
end
...
  i = 0
  while i < 10000
    invoker1
    i+=1
  end
bench1 + indy   bench2 + indy   bench3 + indy

 0.15s



0.113s



0.075s



0.038s



   0s
Moral

• Benchmarks are synthetic
• Every system is different
• Do your own testing
bench_red_black
• Pure-Ruby red/black tree impl
• Build a 100k tree of rand(999_999)
• Delete all nodes
• Build it again
• Search for elements
• In-order walks, min, max
Ruby 1.9.3    JRuby - indy     JRuby + indy
                     bench_red_black
  5s



3.75s



 2.5s



1.25s



  0s
bench_fractal
bench_flipflop_fractal
• Mandelbrot generator
 • Integer loops
 • Floating-point math
• Julia generator using flip-flops
 • I don’t really understand it.
def fractal_flipflop
  w, h = 44, 54
  c = 7 + 42 * w
  a = [0] * w * h
  g = d = 0
  f = proc do |n|
    a[c] += 1
    o = a.map {|z| " :#"[z, 1] * 2 }.join.scan(/.{#{w * 2}}/)
    puts "f" + o.map {|l| l.rstrip }.join("n")
    d += 1 - 2 * ((g ^= 1 << n) >> n)
    c += [1, w, -1, -w][d %= 4]
  end
  1024.times do
    !!(!!(!!(!!(!!(!!(!!(!!(!!(true...
     f[0])...f[1])...f[2])...
     f[3])...f[4])...f[5])...
     f[6])...f[7])...f[8])
  end
end
def fractal_flipflop
  w, h = 44, 54
  c = 7 + 42 * w
  a = [0] * w * h
  g = d = 0
  f = proc do |n|
    a[c] += 1
    o = a.map {|z| " :#"[z, 1] * 2 }.join.scan(/.{#{w * 2}}/)
    puts "f" + o.map {|l| l.rstrip }.join("n")
    d += 1 - 2 * ((g ^= 1 << n) >> n)
    c += [1, w, -1, -w][d %= 4]
  end
  1024.times do
    !!(!!(!!(!!(!!(!!(!!(!!(!!(true...
     f[0])...f[1])...f[2])...
     f[3])...f[4])...f[5])...
     f[6])...f[7])...f[8])
  end
end
Ruby 1.9.3   JRuby - indy    JRuby + indy
                      bench_fractal
  1.5s



1.125s



 0.75s



0.375s



   0s
Ruby 1.9.3      JRuby - indy          JRuby + indy
                      bench_flipflop_fractal
  1.5s



1.125s



 0.75s



0.375s



   0s
Rails?
Rails Perf

• Mixed bag right now...some fast some slow
• JVM JIT limits need to be bumped up
 • Significant gains for some folks
• Long warmup times for so much code
• Work continues!
What Next?
Expand Opto

• Mixed-arity (ADD SLIDES ABOUT WHAT
  WE OPTIMIZE TODAY)
• Super calls
• Much, much lighter-weight closures
• Then what?
Wacky Stuff

• define_method methods?
• method_missing call-throughs?
• respond_to???
• proc tables?
• All possible...but worth it?
The Future
• JRuby will continue to get faster
 • Indy improvements at VM-level
 • Compiler improvements at Ruby level
• If you can’t compete with JVM...
• Still FOSS from top to bottom
 • Don’t be afraid!
Q/A

More Related Content

What's hot

Lifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java BytecodeLifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java BytecodeAlexander Shopov
 
I Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeI Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeAlexander Shopov
 
Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0Hiroshi SHIBATA
 
IronSmalltalk
IronSmalltalkIronSmalltalk
IronSmalltalkESUG
 
Ruby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar Batsov
Ruby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar BatsovRuby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar Batsov
Ruby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar BatsovMichael Kimathi
 
Groovy Up Your Code
Groovy Up Your CodeGroovy Up Your Code
Groovy Up Your CodePaulo Traça
 
PHP.next: Traits
PHP.next: TraitsPHP.next: Traits
PHP.next: TraitsStefan Marr
 
Natural Intelligence ICCS 2010
Natural Intelligence ICCS 2010Natural Intelligence ICCS 2010
Natural Intelligence ICCS 2010fmguler
 
Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009Heiko Behrens
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Rubykim.mens
 
Distributed Key-Value Stores- Featuring Riak
Distributed Key-Value Stores- Featuring RiakDistributed Key-Value Stores- Featuring Riak
Distributed Key-Value Stores- Featuring Riaksamof76
 
Apache Con Us2007 Jcr In Action
Apache Con Us2007 Jcr In ActionApache Con Us2007 Jcr In Action
Apache Con Us2007 Jcr In Actionday
 

What's hot (18)

Lifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java BytecodeLifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java Bytecode
 
Opal compiler
Opal compilerOpal compiler
Opal compiler
 
I Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeI Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java Bytecode
 
Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0Gemification for Ruby 2.5/3.0
Gemification for Ruby 2.5/3.0
 
IronSmalltalk
IronSmalltalkIronSmalltalk
IronSmalltalk
 
Rsltollvm
RsltollvmRsltollvm
Rsltollvm
 
Ruby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar Batsov
Ruby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar BatsovRuby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar Batsov
Ruby 4.0 To Infinity and Beyond at Ruby Conference Kenya 2017 by Bozhidar Batsov
 
In Vogue Dynamic
In Vogue DynamicIn Vogue Dynamic
In Vogue Dynamic
 
南宁会议 Metadata
南宁会议 Metadata南宁会议 Metadata
南宁会议 Metadata
 
Groovy Up Your Code
Groovy Up Your CodeGroovy Up Your Code
Groovy Up Your Code
 
Intro to J Ruby
Intro to J RubyIntro to J Ruby
Intro to J Ruby
 
PHP.next: Traits
PHP.next: TraitsPHP.next: Traits
PHP.next: Traits
 
Natural Intelligence ICCS 2010
Natural Intelligence ICCS 2010Natural Intelligence ICCS 2010
Natural Intelligence ICCS 2010
 
Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Ruby
 
Distributed Key-Value Stores- Featuring Riak
Distributed Key-Value Stores- Featuring RiakDistributed Key-Value Stores- Featuring Riak
Distributed Key-Value Stores- Featuring Riak
 
ZF2 Presentation @PHP Tour 2011 in Lille
ZF2 Presentation @PHP Tour 2011 in LilleZF2 Presentation @PHP Tour 2011 in Lille
ZF2 Presentation @PHP Tour 2011 in Lille
 
Apache Con Us2007 Jcr In Action
Apache Con Us2007 Jcr In ActionApache Con Us2007 Jcr In Action
Apache Con Us2007 Jcr In Action
 

Similar to High Performance Ruby - Golden Gate RubyConf 2012

Invoke dynamic your api to hotspot
Invoke dynamic your api to hotspotInvoke dynamic your api to hotspot
Invoke dynamic your api to hotspotBoundary
 
InvokeDynamic - You Ain't Seen Nothin Yet
InvokeDynamic - You Ain't Seen Nothin YetInvokeDynamic - You Ain't Seen Nothin Yet
InvokeDynamic - You Ain't Seen Nothin YetCharles Nutter
 
Invokedynamic / JSR-292
Invokedynamic / JSR-292Invokedynamic / JSR-292
Invokedynamic / JSR-292ytoshima
 
GOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter SlidesGOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter SlidesAlexandra Masterson
 
The Ruby Racer: under the hood
The Ruby Racer: under the hoodThe Ruby Racer: under the hood
The Ruby Racer: under the hoodcowboyd
 
Spring framework
Spring frameworkSpring framework
Spring frameworkAircon Chen
 
Swift Micro-services and AWS Technologies
Swift Micro-services and AWS TechnologiesSwift Micro-services and AWS Technologies
Swift Micro-services and AWS TechnologiesSimonPilkington8
 
JRuby: What's Different (RORO Melbourne October 2011)
JRuby: What's Different (RORO Melbourne October 2011)JRuby: What's Different (RORO Melbourne October 2011)
JRuby: What's Different (RORO Melbourne October 2011)Charles Nutter
 
2장. Runtime Data Areas
2장. Runtime Data Areas2장. Runtime Data Areas
2장. Runtime Data Areas김 한도
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015Charles Nutter
 
XS Boston 2008 Paravirt Ops in Linux IA64
XS Boston 2008 Paravirt Ops in Linux IA64XS Boston 2008 Paravirt Ops in Linux IA64
XS Boston 2008 Paravirt Ops in Linux IA64The Linux Foundation
 
Quick Intro To JRuby
Quick Intro To JRubyQuick Intro To JRuby
Quick Intro To JRubyFrederic Jean
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesCharles Nutter
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015Charles Nutter
 
Практики применения JRuby
Практики применения JRubyПрактики применения JRuby
Практики применения JRuby.toster
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applicationsRuslan Shevchenko
 

Similar to High Performance Ruby - Golden Gate RubyConf 2012 (20)

Invoke dynamic your api to hotspot
Invoke dynamic your api to hotspotInvoke dynamic your api to hotspot
Invoke dynamic your api to hotspot
 
InvokeDynamic - You Ain't Seen Nothin Yet
InvokeDynamic - You Ain't Seen Nothin YetInvokeDynamic - You Ain't Seen Nothin Yet
InvokeDynamic - You Ain't Seen Nothin Yet
 
Invokedynamic / JSR-292
Invokedynamic / JSR-292Invokedynamic / JSR-292
Invokedynamic / JSR-292
 
GOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter SlidesGOTO Night with Charles Nutter Slides
GOTO Night with Charles Nutter Slides
 
The Ruby Racer: under the hood
The Ruby Racer: under the hoodThe Ruby Racer: under the hood
The Ruby Racer: under the hood
 
Ruby on the JVM
Ruby on the JVMRuby on the JVM
Ruby on the JVM
 
Spring framework
Spring frameworkSpring framework
Spring framework
 
Swift Micro-services and AWS Technologies
Swift Micro-services and AWS TechnologiesSwift Micro-services and AWS Technologies
Swift Micro-services and AWS Technologies
 
Java Performance MythBusters
Java Performance MythBustersJava Performance MythBusters
Java Performance MythBusters
 
JRuby: What's Different (RORO Melbourne October 2011)
JRuby: What's Different (RORO Melbourne October 2011)JRuby: What's Different (RORO Melbourne October 2011)
JRuby: What's Different (RORO Melbourne October 2011)
 
2장. Runtime Data Areas
2장. Runtime Data Areas2장. Runtime Data Areas
2장. Runtime Data Areas
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015
 
XS Boston 2008 Paravirt Ops in Linux IA64
XS Boston 2008 Paravirt Ops in Linux IA64XS Boston 2008 Paravirt Ops in Linux IA64
XS Boston 2008 Paravirt Ops in Linux IA64
 
Quick Intro To JRuby
Quick Intro To JRubyQuick Intro To JRuby
Quick Intro To JRuby
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015
 
Практики применения JRuby
Практики применения JRubyПрактики применения JRuby
Практики применения JRuby
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applications
 
Java 10, Java 11 and beyond
Java 10, Java 11 and beyondJava 10, Java 11 and beyond
Java 10, Java 11 and beyond
 
Understanding the Dalvik Virtual Machine
Understanding the Dalvik Virtual MachineUnderstanding the Dalvik Virtual Machine
Understanding the Dalvik Virtual Machine
 

More from Charles Nutter

The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018Charles Nutter
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandDown the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandCharles Nutter
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Charles Nutter
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMCharles Nutter
 
Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaCharles Nutter
 
Open Source Software Needs You!
Open Source Software Needs You!Open Source Software Needs You!
Open Source Software Needs You!Charles Nutter
 
InvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method HandlesInvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method HandlesCharles Nutter
 
Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Charles Nutter
 
Doing Open Source the Right Way
Doing Open Source the Right WayDoing Open Source the Right Way
Doing Open Source the Right WayCharles Nutter
 
Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014Charles Nutter
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Charles Nutter
 
Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Charles Nutter
 
Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Charles Nutter
 
The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013Charles Nutter
 
High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013Charles Nutter
 
Invokedynamic in 45 Minutes
Invokedynamic in 45 MinutesInvokedynamic in 45 Minutes
Invokedynamic in 45 MinutesCharles Nutter
 
Invokedynamic: Tales from the Trenches
Invokedynamic: Tales from the TrenchesInvokedynamic: Tales from the Trenches
Invokedynamic: Tales from the TrenchesCharles Nutter
 
Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012Charles Nutter
 

More from Charles Nutter (20)

The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandDown the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM Wonderland
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVM
 
Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible Java
 
Open Source Software Needs You!
Open Source Software Needs You!Open Source Software Needs You!
Open Source Software Needs You!
 
InvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method HandlesInvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method Handles
 
Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Over 9000: JRuby in 2015
Over 9000: JRuby in 2015
 
Doing Open Source the Right Way
Doing Open Source the Right WayDoing Open Source the Right Way
Doing Open Source the Right Way
 
JRuby: The Hard Parts
JRuby: The Hard PartsJRuby: The Hard Parts
JRuby: The Hard Parts
 
Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013
 
Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013
 
Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013
 
Down the Rabbit Hole
Down the Rabbit HoleDown the Rabbit Hole
Down the Rabbit Hole
 
The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013
 
High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013
 
Invokedynamic in 45 Minutes
Invokedynamic in 45 MinutesInvokedynamic in 45 Minutes
Invokedynamic in 45 Minutes
 
Invokedynamic: Tales from the Trenches
Invokedynamic: Tales from the TrenchesInvokedynamic: Tales from the Trenches
Invokedynamic: Tales from the Trenches
 
Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012
 

Recently uploaded

Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...Americas Got Grants
 
EUDR Info Meeting Ethiopian coffee exporters
EUDR Info Meeting Ethiopian coffee exportersEUDR Info Meeting Ethiopian coffee exporters
EUDR Info Meeting Ethiopian coffee exportersPeter Horsten
 
Data Analytics Strategy Toolkit and Templates
Data Analytics Strategy Toolkit and TemplatesData Analytics Strategy Toolkit and Templates
Data Analytics Strategy Toolkit and TemplatesAurelien Domont, MBA
 
Interoperability and ecosystems: Assembling the industrial metaverse
Interoperability and ecosystems:  Assembling the industrial metaverseInteroperability and ecosystems:  Assembling the industrial metaverse
Interoperability and ecosystems: Assembling the industrial metaverseSiemens
 
Go for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptx
Go for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptxGo for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptx
Go for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptxRakhi Bazaar
 
Environmental Impact Of Rotary Screw Compressors
Environmental Impact Of Rotary Screw CompressorsEnvironmental Impact Of Rotary Screw Compressors
Environmental Impact Of Rotary Screw Compressorselgieurope
 
14680-51-4.pdf Good quality CAS Good quality CAS
14680-51-4.pdf  Good  quality CAS Good  quality CAS14680-51-4.pdf  Good  quality CAS Good  quality CAS
14680-51-4.pdf Good quality CAS Good quality CAScathy664059
 
Pitch Deck Teardown: Xpanceo's $40M Seed deck
Pitch Deck Teardown: Xpanceo's $40M Seed deckPitch Deck Teardown: Xpanceo's $40M Seed deck
Pitch Deck Teardown: Xpanceo's $40M Seed deckHajeJanKamps
 
Unveiling the Soundscape Music for Psychedelic Experiences
Unveiling the Soundscape Music for Psychedelic ExperiencesUnveiling the Soundscape Music for Psychedelic Experiences
Unveiling the Soundscape Music for Psychedelic ExperiencesDoe Paoro
 
20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf
20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf
20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdfChris Skinner
 
Planetary and Vedic Yagyas Bring Positive Impacts in Life
Planetary and Vedic Yagyas Bring Positive Impacts in LifePlanetary and Vedic Yagyas Bring Positive Impacts in Life
Planetary and Vedic Yagyas Bring Positive Impacts in LifeBhavana Pujan Kendra
 
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...ssuserf63bd7
 
Darshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdfDarshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdfShashank Mehta
 
Excvation Safety for safety officers reference
Excvation Safety for safety officers referenceExcvation Safety for safety officers reference
Excvation Safety for safety officers referencessuser2c065e
 
Appkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptxAppkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptxappkodes
 
How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...
How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...
How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...Hector Del Castillo, CPM, CPMM
 
Introducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applicationsIntroducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applicationsKnowledgeSeed
 
NAB Show Exhibitor List 2024 - Exhibitors Data
NAB Show Exhibitor List 2024 - Exhibitors DataNAB Show Exhibitor List 2024 - Exhibitors Data
NAB Show Exhibitor List 2024 - Exhibitors DataExhibitors Data
 
Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...Peter Ward
 

Recently uploaded (20)

Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...
 
EUDR Info Meeting Ethiopian coffee exporters
EUDR Info Meeting Ethiopian coffee exportersEUDR Info Meeting Ethiopian coffee exporters
EUDR Info Meeting Ethiopian coffee exporters
 
Data Analytics Strategy Toolkit and Templates
Data Analytics Strategy Toolkit and TemplatesData Analytics Strategy Toolkit and Templates
Data Analytics Strategy Toolkit and Templates
 
Interoperability and ecosystems: Assembling the industrial metaverse
Interoperability and ecosystems:  Assembling the industrial metaverseInteroperability and ecosystems:  Assembling the industrial metaverse
Interoperability and ecosystems: Assembling the industrial metaverse
 
Go for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptx
Go for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptxGo for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptx
Go for Rakhi Bazaar and Pick the Latest Bhaiya Bhabhi Rakhi.pptx
 
Environmental Impact Of Rotary Screw Compressors
Environmental Impact Of Rotary Screw CompressorsEnvironmental Impact Of Rotary Screw Compressors
Environmental Impact Of Rotary Screw Compressors
 
14680-51-4.pdf Good quality CAS Good quality CAS
14680-51-4.pdf  Good  quality CAS Good  quality CAS14680-51-4.pdf  Good  quality CAS Good  quality CAS
14680-51-4.pdf Good quality CAS Good quality CAS
 
Pitch Deck Teardown: Xpanceo's $40M Seed deck
Pitch Deck Teardown: Xpanceo's $40M Seed deckPitch Deck Teardown: Xpanceo's $40M Seed deck
Pitch Deck Teardown: Xpanceo's $40M Seed deck
 
Unveiling the Soundscape Music for Psychedelic Experiences
Unveiling the Soundscape Music for Psychedelic ExperiencesUnveiling the Soundscape Music for Psychedelic Experiences
Unveiling the Soundscape Music for Psychedelic Experiences
 
20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf
20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf
20220816-EthicsGrade_Scorecard-JP_Morgan_Chase-Q2-63_57.pdf
 
Planetary and Vedic Yagyas Bring Positive Impacts in Life
Planetary and Vedic Yagyas Bring Positive Impacts in LifePlanetary and Vedic Yagyas Bring Positive Impacts in Life
Planetary and Vedic Yagyas Bring Positive Impacts in Life
 
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
 
Darshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdfDarshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdf
 
Excvation Safety for safety officers reference
Excvation Safety for safety officers referenceExcvation Safety for safety officers reference
Excvation Safety for safety officers reference
 
Appkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptxAppkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptx
 
The Bizz Quiz-E-Summit-E-Cell-IITPatna.pptx
The Bizz Quiz-E-Summit-E-Cell-IITPatna.pptxThe Bizz Quiz-E-Summit-E-Cell-IITPatna.pptx
The Bizz Quiz-E-Summit-E-Cell-IITPatna.pptx
 
How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...
How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...
How Generative AI Is Transforming Your Business | Byond Growth Insights | Apr...
 
Introducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applicationsIntroducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applications
 
NAB Show Exhibitor List 2024 - Exhibitors Data
NAB Show Exhibitor List 2024 - Exhibitors DataNAB Show Exhibitor List 2024 - Exhibitors Data
NAB Show Exhibitor List 2024 - Exhibitors Data
 
Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...
 

High Performance Ruby - Golden Gate RubyConf 2012

  • 2. Hiya • Charles Oliver Nutter • headius@headius.com • @headius • JVM language guy at Red Hat (JBoss)
  • 3. Performance? • Writing code • Man hours more expensive than CPU hours • Developer contentedness • Running code • Straight line
  • 4. High Performance? • Faster than... • ...other Ruby impls? • ...other language runtimes? • ...unmanaged languages, like C? • ...you need it to be?
  • 5. “Fast Enough” • 1.8.7 was fast enough • 1.9.3 is fast enough • Unless it’s not fast enough • Does it matter?
  • 6. Performance Wall • Move to a different runtime • Move to a different language • ...in whole or part
  • 7. If you’re not writing perf- sensitive code in Ruby, you’re giving up too easily.
  • 8. Native Extensions • Not universally bad • Just bad in MRI • Invasive • Pointers • Few guarantees
  • 9. What We Want • Faster execution • Better GC • Parallel execution • Big data
  • 10. What We Can’t Have • Faster execution • Better GC • Parallel execution • Big data
  • 11. Different Approach • Build our own runtime? • YARV, Rubinius, MacRuby • Use an existing runtime? • JRuby, MagLev, MacRuby, IronRuby
  • 12. Build or Buy • Making a new VM is “easy” • Making it competitive is really hard • I mean really, really, really hard
  • 13. JVM • 15+ years of engineering by whole teams • FOSS • Fastest VM available • Best GCs available • Full parallel threading with guarantees • Broad platform support
  • 14. But Java is Slow! • Java is very, very fast • Literally, C fast in many cases • Java applications can be slow • Oh hey, just like Ruby? • The way you write code is more important than the language you use.
  • 15. JRuby • Java (and Ruby) impl of Ruby on JVM • Same memory, threading model • JRuby JITs to JVM bytecode • End of story, right?
  • 16. Long, Hard Road • Interpreter optimization • JVM bytecode compiler • Optimizing core class methods • Lather, rinse, and repeat
  • 17.
  • 18. Align with JVM • Individual arguments on call stack • JVM local variables • Avoid artificial framing • Avoid inter-call goo • Eliminate unnecessary work
  • 19. Unnecessary Work • Modules are maps • Name to method • Name to constant • Name to class var • Instance variables as maps • Wasted cycles without caching
  • 20. Method Lookup • Inside a class/module • Current class’s methods (a map) • Methods retrieved from class + ancestors • Serial or switch indicates staleness • Weak list of child classes • Class mutation cascades down hierarchy
  • 21. Thing Person Place obj.to_s Rubyist Other
  • 22. Method lookups go up-hierarchy Thing Person Place obj.to_s Rubyist Other
  • 23. to_s Method lookups go up-hierarchy Thing Person Place obj.to_s Rubyist Other
  • 24. to_s Method lookups go up-hierarchy Thing Lookup target caches result Person Place obj.to_s Rubyist Other
  • 25. Method lookups go up-hierarchy Thing Lookup target caches result Person Place to_s obj.to_s Rubyist Other
  • 26. Method lookups go up-hierarchy Thing Lookup target caches result Modification cascades down Person Place to_s obj.to_s Rubyist Other
  • 27. Method lookups go up-hierarchy Thing to_s Lookup target caches result Modification cascades down Person Place to_s obj.to_s Rubyist Other
  • 28. Constant Lookup • Cache at lookup site • Global serial/switch indicates staleness • Complexities of lookup, etc • Joy of Ruby interfering with Joy of Opto • Modifying constants triggers invalidation
  • 29. Instance Vars • Class holds a table of offsets • Object holds array of values • Call site caches offset plus class ID • Same class, no lookup cost • Can be polymorphically chained
  • 30. Optimizing Ruby • Make calls fast • Make constants free • Make instance variables cheap • Make closures lightweight • TODO
  • 33. Invoke? That’s one use, but there are many others
  • 35. Dynamic? Dynamic typing is a common reason, but there are many others
  • 38. JVM 101 200 opcodes Ten (or 16) “data endpoints”
  • 39. JVM 101 200 opcodes Ten (or 16) “data endpoints” Invocation invokevirtual invokeinterface invokestatic invokespecial
  • 40. JVM 101 200 opcodes Ten (or 16) “data endpoints” Invocation Field Access invokevirtual getfield invokeinterface setfield invokestatic getstatic invokespecial setstatic
  • 41. JVM 101 200 opcodes Ten (or 16) “data endpoints” Invocation Field Access Array Access invokevirtual getfield *aload invokeinterface setfield *astore invokestatic getstatic b,s,c,i,l,d,f,a invokespecial setstatic
  • 42. JVM 101 200 opcodes Ten (or 16) “data endpoints” Invocation Field Access Array Access invokevirtual getfield *aload invokeinterface setfield *astore invokestatic getstatic b,s,c,i,l,d,f,a invokespecial setstatic All Java code revolves around these endpoints Remaining ops are stack, local vars, flow control allocation, and math/boolean/bit operations
  • 44. JVM Opcodes Invocation Field Access Array Access invokevirtual getfield *aload invokeinterface setfield *astore invokestatic getstatic b,s,c,i,l,d,f,a invokespecial setstatic
  • 45. JVM Opcodes Invocation Field Access Array Access invokevirtual getfield *aload invokeinterface setfield *astore invokestatic getstatic b,s,c,i,l,d,f,a invokespecial setstatic Stack Local Vars Flow Control Allocation Boolean and Numeric
  • 46. JVM Opcodes Invocation Field Access Array Access invokevirtual getfield *aload invokeinterface setfield *astore invokestatic getstatic b,s,c,i,l,d,f,a invokespecial setstatic Stack Local Vars Flow Control Allocation Boolean and Numeric
  • 47. JVM Opcodes Invocation Field Access Array Access invokevirtual getfield *aload invokeinterface setfield *astore invokestatic getstatic b,s,c,i,l,d,f,a invokespecial setstatic Stack Local Vars Flow Control Allocation Boolean and Numeric
  • 48.
  • 49. In Detail • JRuby generates code with indy calls • JVM at first call asks JRuby what to do • JRuby provides function pointers to code • Pointers include guards, invalidation logic • JRuby and JVM cooperate on optimizing
  • 50.
  • 52. invokedynamic bytecode bo ot stra p m et ho d
  • 53. invokedynamic bytecode bo ot stra p m et ho d method handles
  • 54. invokedynamic bytecode target method bo ot stra p m et ho d method handles
  • 55. invokedynamic bytecode target method bo ot stra p m et ho d method handles
  • 56. invokedynamic bytecode target method bo ot stra p m et ho d method handles
  • 57. Dynamic Invocation Target Object associated with obj.foo() JVM Method Table def foo ... def bar ...
  • 58. Dynamic Invocation VM Operations Target Object associated with obj.foo() JVM Method Table Call Site def foo ... def bar ...
  • 59. Dynamic Invocation VM Operations Target Object associated with obj.foo() JVM Method Table Call Site def foo ... def bar ...
  • 60. Dynamic Invocation VM Operations Method Lookup Target Object associated with obj.foo() JVM Method Table Call Site def foo ... def foo ... def bar ...
  • 61. Dynamic Invocation VM Operations Method Lookup Target Branch Object associated with obj.foo() JVM Method Table Call Site def foo ... def foo ... def bar ...
  • 62. Dynamic Invocation VM Operations Method Lookup Target Branch Method Cache Object associated with obj.foo() JVM def foo ... Method Table Call Site def foo ... def bar ...
  • 63. Constants JVM Constant MY_CONST Lookup Call Site
  • 64. Constants VM Operations JVM Constant MY_CONST Lookup Call Site
  • 65. Constants VM Operations JVM Constant MY_CONST Lookup Call Site
  • 66. Constants VM Operations Lookup Value JVM Constant MY_CONST value Lookup Call Site
  • 67. Constants VM Operations Lookup Value Bind Permanently JVM Constant MY_CONST value Lookup Call Site
  • 68. Instance Variables Target Object associated with @bar JVM Offset Table “@foo” => 0 “@bar” => 1
  • 69. Instance Variables VM Operations Target Object associated with @bar JVM Offset Table Access Site “@foo” => 0 “@bar” => 1
  • 70. Instance Variables VM Operations Instance Var Lookup Target Object associated with @bar JVM Offset Table Access Site “@foo” => 0 “@bar” => 1
  • 71. Instance Variables VM Operations Instance Var Lookup Target Offset Cache Object associated with @bar JVM 1 Offset Table Access Site “@foo” => 0 “@bar” => 1
  • 72. Instance Variables VM Operations Instance Var Lookup Target Offset Cache Access Object Object associated with @bar JVM 1 Offset Table Access Site “@foo” => 0 “@bar” => 1
  • 73. Instance Variables VM Operations Instance Var Lookup Target Offset Cache Access Object Object associated with @bar JVM 1 Offset Table Access Site “@foo” => 0 “@bar” => 1
  • 74. InvokeDynamic lets JRuby teach the JVM how Ruby works
  • 75. How Do We Know We’ve Succeeded? • Benchmarking • Monitoring • User reports
  • 76. Benchmarking is Hard • Runtimes may improve over time • Optimizer may eliminate useless code • Small systems are completely different • Know how your runtime optimizes!
  • 77. bench_empty_method def foo; self; end i = 0 while i < 10_000_000 foo; foo; foo; foo; foo i += 1 end
  • 78. Ruby 1.9.3 JRuby JRuby + indy 4s 3s 2s 1s 0s ZOMG 40X FA STER!
  • 80. One slow runtime screws up the table
  • 81.
  • 82. ...do comparisons as ratios against a norm
  • 83.
  • 84. JRuby calls empty methods really fast!!!
  • 86. Ruby 1.9.3 JRuby JRuby + indy 4s 3s 2s 1s 0s
  • 87. JVM Opto 101 • JITs code bodies after 10k calls • No 10k calls, no JIT (generally) • Inlines up to two targets • Optimistic • Early decisions may be wrong • Small code looks drastically different
  • 88. SMALL CODE IS DIFFERENT THAN LARGE CODE
  • 89. Inlining • Call site in method A and method B match • JVM treats them as though B lived in A • No call overhead • Variables visible across call boundary • More complete view for optimization
  • 90. Optimistic • Say we have a system... • The only method dynamically called is “foo” • All logic for dyncall revolves around “foo” • Hotspot thinks all dyncalls will be “foo”
  • 91. bench_empty_method2 def foo; self; end def bar1; self; end def bar2; self; end i = 0 while i < 10_000_000 bar1; bar1; bar1; bar1; bar1 bar2; bar2; bar2; bar2; bar2 i += 1 end ...
  • 92. bench1 bench2 bench1 + indy bench2 + indy 0.7s 0.525s 0.35s 0.175s 0s
  • 93. bench1 + rbx bench2 + rbx bench1 + indy bench2 + indy 0.4s 0.3s 0.2s 0.1s 0s
  • 94. What Happened? • An unrelated change slowed our bench? • Not really unrelated • Hotspot optimizes early loop first • Later loop is different...calls “foo” • Assumptions change, perf looks different
  • 95. Benchmarking is Not Enough • Need to monitor runtime optimization • JIT compilation • Inlining • Eventual native code (x86 ASM) • Fun?
  • 96. 1711 4 % bench_empty_method::block_0$RUBY$__file__ @ 56 (171 bytes) @ 59 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot) @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot) @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot) @ 16 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot) @ 1 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot) @ 12 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 29 java.lang.invoke.MethodHandle::invokeExact (35 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot) @ 3 org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass (17 bytes) inline (hot) @ 5 org.jruby.RubyBasicObject::getMetaClass (5 bytes) inline (hot) @ 14 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 31 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 6 bench_empty_method::method__0$RUBY$foo (2 bytes) inline (hot) @ 68 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot) @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot) @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
  • 97. 1711 4 % bench_empty_method::block_0$RUBY$__file__ @ 56 (171 bytes) @ 59 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot) @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot) @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot) @ 16 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot) @ 1 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot) @ 12 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 29 java.lang.invoke.MethodHandle::invokeExact (35 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot) @ 3 org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass (17 bytes) inline (hot) @ 5 org.jruby.RubyBasicObject::getMetaClass (5 bytes) inline (hot) @ 14 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 31 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 6 bench_empty_method::method__0$RUBY$foo (2 bytes) inline (hot) @ 68 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot) @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot) @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
  • 98. 1711 4 % bench_empty_method::block_0$RUBY$__file__ @ 56 (171 bytes) @ 59 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot) @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot) @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot) @ 16 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot) @ 1 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot) @ 12 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 29 java.lang.invoke.MethodHandle::invokeExact (35 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot) @ 3 org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass (17 bytes) inline (hot) @ 5 org.jruby.RubyBasicObject::getMetaClass (5 bytes) inline (hot) @ 14 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 31 java.lang.invoke.MethodHandle::invokeExact (10 bytes) inline (hot) @ 6 bench_empty_method::method__0$RUBY$foo (2 bytes) inline (hot) @ 68 java.lang.invoke.MethodHandle::invokeExact (33 bytes) inline (hot) @ 5 java.lang.invoke.MethodHandle::invokeExact (20 bytes) inline (hot) @ 2 java.lang.invoke.MethodHandle::invokeExact (9 bytes) inline (hot) @ 2 java.lang.invoke.MutableCallSite::getTarget (5 bytes) inline (hot)
  • 99. Decoding compiled method 0x000000010549d7d0: Code: [Entry Point] [Verified Entry Point] [Constants] # {method} 'method__0$RUBY$foo' '(Lbench_empty_method;Lorg/jruby/runtime/ThreadContext;Lorg/jruby/ runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;' in 'bench_empty_method' # parm0: rsi:rsi = 'bench_empty_method' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext' # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x20] (sp of caller) 0x000000010549d900: sub $0x18,%rsp 0x000000010549d907: mov %rbp,0x10(%rsp) ;*synchronization entry ; - bench_empty_method::method__0$RUBY$foo@-1 (line 3) 0x000000010549d90c: mov %rcx,%rax 0x000000010549d90f: add $0x10,%rsp 0x000000010549d913: pop %rbp 0x000000010549d914: test %eax,-0xe9f91a(%rip) # 0x00000001045fe000 ; {poll_return} 0x000000010549d91a: retq
  • 100. Decoding compiled method 0x000000010549d7d0: Code: [Entry Point] [Verified Entry Point] [Constants] # {method} 'method__0$RUBY$foo' '(Lbench_empty_method;Lorg/jruby/runtime/ThreadContext;Lorg/jruby/ runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;' in 'bench_empty_method' # parm0: rsi:rsi = 'bench_empty_method' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext' # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x20] (sp of caller) 0x000000010549d900: sub $0x18,%rsp 0x000000010549d907: mov %rbp,0x10(%rsp) ;*synchronization entry ; - bench_empty_method::method__0$RUBY$foo@-1 (line 3) 0x000000010549d90c: mov %rcx,%rax 0x000000010549d90f: add $0x10,%rsp 0x000000010549d913: pop %rbp 0x000000010549d914: test %eax,-0xe9f91a(%rip) # 0x00000001045fe000 ; {poll_return} 0x000000010549d91a: retq
  • 101. Decoding compiled method 0x000000010549d7d0: Code: [Entry Point] [Verified Entry Point] [Constants] # {method} 'method__0$RUBY$foo' '(Lbench_empty_method;Lorg/jruby/runtime/ThreadContext;Lorg/jruby/ runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;' in 'bench_empty_method' # parm0: rsi:rsi = 'bench_empty_method' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext' # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x20] (sp of caller) 0x000000010549d900: sub $0x18,%rsp 0x000000010549d907: mov %rbp,0x10(%rsp) ;*synchronization entry ; - bench_empty_method::method__0$RUBY$foo@-1 (line 3) 0x000000010549d90c: mov %rcx,%rax 0x000000010549d90f: add $0x10,%rsp 0x000000010549d913: pop %rbp 0x000000010549d914: test %eax,-0xe9f91a(%rip) # 0x00000001045fe000 ; {poll_return} 0x000000010549d91a: retq
  • 102. bench_empty_method3 def invoker1 i = 0 while i < 1000 foo; foo; foo; foo; foo i+=1 end end ... i = 0 while i < 10000 invoker1 i+=1 end
  • 103. bench1 + indy bench2 + indy bench3 + indy 0.15s 0.113s 0.075s 0.038s 0s
  • 104. Moral • Benchmarks are synthetic • Every system is different • Do your own testing
  • 105. bench_red_black • Pure-Ruby red/black tree impl • Build a 100k tree of rand(999_999) • Delete all nodes • Build it again • Search for elements • In-order walks, min, max
  • 106. Ruby 1.9.3 JRuby - indy JRuby + indy bench_red_black 5s 3.75s 2.5s 1.25s 0s
  • 107. bench_fractal bench_flipflop_fractal • Mandelbrot generator • Integer loops • Floating-point math • Julia generator using flip-flops • I don’t really understand it.
  • 108.
  • 109. def fractal_flipflop w, h = 44, 54 c = 7 + 42 * w a = [0] * w * h g = d = 0 f = proc do |n| a[c] += 1 o = a.map {|z| " :#"[z, 1] * 2 }.join.scan(/.{#{w * 2}}/) puts "f" + o.map {|l| l.rstrip }.join("n") d += 1 - 2 * ((g ^= 1 << n) >> n) c += [1, w, -1, -w][d %= 4] end 1024.times do !!(!!(!!(!!(!!(!!(!!(!!(!!(true... f[0])...f[1])...f[2])... f[3])...f[4])...f[5])... f[6])...f[7])...f[8]) end end
  • 110. def fractal_flipflop w, h = 44, 54 c = 7 + 42 * w a = [0] * w * h g = d = 0 f = proc do |n| a[c] += 1 o = a.map {|z| " :#"[z, 1] * 2 }.join.scan(/.{#{w * 2}}/) puts "f" + o.map {|l| l.rstrip }.join("n") d += 1 - 2 * ((g ^= 1 << n) >> n) c += [1, w, -1, -w][d %= 4] end 1024.times do !!(!!(!!(!!(!!(!!(!!(!!(!!(true... f[0])...f[1])...f[2])... f[3])...f[4])...f[5])... f[6])...f[7])...f[8]) end end
  • 111.
  • 112. Ruby 1.9.3 JRuby - indy JRuby + indy bench_fractal 1.5s 1.125s 0.75s 0.375s 0s
  • 113. Ruby 1.9.3 JRuby - indy JRuby + indy bench_flipflop_fractal 1.5s 1.125s 0.75s 0.375s 0s
  • 114. Rails?
  • 115. Rails Perf • Mixed bag right now...some fast some slow • JVM JIT limits need to be bumped up • Significant gains for some folks • Long warmup times for so much code • Work continues!
  • 117. Expand Opto • Mixed-arity (ADD SLIDES ABOUT WHAT WE OPTIMIZE TODAY) • Super calls • Much, much lighter-weight closures • Then what?
  • 118. Wacky Stuff • define_method methods? • method_missing call-throughs? • respond_to??? • proc tables? • All possible...but worth it?
  • 119. The Future • JRuby will continue to get faster • Indy improvements at VM-level • Compiler improvements at Ruby level • If you can’t compete with JVM... • Still FOSS from top to bottom • Don’t be afraid!
  • 120. Q/A

Editor's Notes

  1. \n
  2. \n
  3. Ruby is already a &amp;#x201C;high performance&amp;#x201D; language when it comes to writing code\n
  4. \n
  5. \n
  6. \n
  7. Many better reasons... differently expressive languages, differently fun, designed for the problem at hand...\n
  8. \n
  9. \n
  10. \n
  11. \n
  12. _why&amp;#x2019;s potion, MA Cournoyer&amp;#x2019;s tinyrb, the thousand other Ruby impls\nRubinius? 5 years with two fulltime people, hundreds of contributors. 1.5 years since last release.\n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. Two hard things in CS: cache invalidation and naming things (and off by one errors)\n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. Also loading constants, which are read-only; not as interesting\n
  46. Also loading constants, which are read-only; not as interesting\n
  47. Also loading constants, which are read-only; not as interesting\n
  48. Also loading constants, which are read-only; not as interesting\n
  49. Also loading constants, which are read-only; not as interesting\n
  50. Also loading constants, which are read-only; not as interesting\n
  51. Also loading constants, which are read-only; not as interesting\n
  52. Also loading constants, which are read-only; not as interesting\n
  53. Also loading constants, which are read-only; not as interesting\n
  54. Also loading constants, which are read-only; not as interesting\n
  55. Also loading constants, which are read-only; not as interesting\n
  56. Also loading constants, which are read-only; not as interesting\n
  57. Also loading constants, which are read-only; not as interesting\n
  58. Also loading constants, which are read-only; not as interesting\n
  59. Also loading constants, which are read-only; not as interesting\n
  60. Also loading constants, which are read-only; not as interesting\n
  61. Also loading constants, which are read-only; not as interesting\n
  62. Also loading constants, which are read-only; not as interesting\n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. Comparisons as ratios...sometimes. Often a stark difference sells the point better.\n
  138. \n
  139. Comparisons as ratios...sometimes. Often a stark difference sells the point better.\n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n
  153. \n
  154. \n
  155. \n
  156. \n
  157. \n
  158. \n
  159. \n
  160. \n
  161. \n
  162. \n
  163. \n
  164. \n
  165. \n
  166. \n
  167. \n
  168. \n
  169. \n
  170. Rails applications are incredibly big systems compared to benchmarks\n
  171. \n
  172. \n
  173. \n
  174. \n
  175. \n