Skip to content

JRuby Performance results

Nikolay edited this page Mar 2, 2015 · 6 revisions

My results on an old Thinkpad 410 running JRuby 1.7.18 and Java 8.

Very preliminary results

There were 3 tests where the faster strategy was different to the MRI result. They were:

Each vs For loop

each is 1.29x slower than for. In MRI each was 1.05x faster.

Each with index vs while

each is 1.15x faster

String concatenation

Apart from the inline concatenation which is handled by the parser (I presume), JRuby prefers the opposite ways of concatenating strings to MRI.

Raw Results from rake run_benchmark

joconnor@joconnor-ThinkPad-T410:~/NetBeansProjects/github-gems/fast-ruby$ rake run_benchmark
$ ruby -v code/general/begin-rescue-vs-respond-to.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
      begin...rescue       701 i/100ms
         respond_to?     30118 i/100ms
-------------------------------------------------
      begin...rescue     7602.0 (±14.4%) i/s -      36452 in   5.034000s
         respond_to?  1116691.1 (±5.4%) i/s -    5571830 in   5.015001s

Comparison:
         respond_to?:  1116691.1 i/s
      begin...rescue:     7602.0 i/s - 146.89x slower

$ ruby -v code/general/define_method-vs-module-eval.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
module_eval with string
                           132 i/100ms
       define_method       205 i/100ms
-------------------------------------------------
module_eval with string
                         1860.7 (±17.6%) i/s -       7788 in   5.019000s
       define_method     2452.9 (±24.0%) i/s -       9430 in   5.070000s

Comparison:
       define_method:     2452.9 i/s
module_eval with string:     1860.7 i/s - 1.32x slower

$ ruby -v code/general/attr-accessor-vs-getter-and-setter.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
   getter_and_setter     28487 i/100ms
       attr_accessor     29179 i/100ms
-------------------------------------------------
   getter_and_setter   717730.5 (±8.4%) i/s -    3617849 in   5.159000s
       attr_accessor   951122.8 (±4.3%) i/s -    4756177 in   5.011000s

Comparison:
       attr_accessor:   951122.8 i/s
   getter_and_setter:   717730.5 i/s - 1.33x slower

$ ruby -v code/general/assignment.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
 Parallel Assignment     29313 i/100ms
Sequential Assignment
                         33587 i/100ms
-------------------------------------------------
 Parallel Assignment   982931.9 (±11.7%) i/s -    4631454 in   5.016000s
Sequential Assignment
                      1145346.2 (±3.2%) i/s -    5709790 in   4.991000s

Comparison:
Sequential Assignment:  1145346.2 i/s
 Parallel Assignment:   982931.9 i/s - 1.17x slower

$ ruby -v code/hash/merge-vs-merge-bang.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
          Hash#merge       178 i/100ms
         Hash#merge!      1460 i/100ms
-------------------------------------------------
          Hash#merge     2160.1 (±5.7%) i/s -      10858 in   5.046000s
         Hash#merge!    18545.9 (±3.0%) i/s -      93440 in   5.043000s

Comparison:
         Hash#merge!:    18545.9 i/s
          Hash#merge:     2160.1 i/s - 8.59x slower

$ ruby -v code/hash/keys-each-vs-each_key.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
      Hash#keys.each     19330 i/100ms
       Hash#each_key     21541 i/100ms
-------------------------------------------------
      Hash#keys.each   467405.1 (±6.1%) i/s -    2338930 in   5.025000s
       Hash#each_key   504252.5 (±3.2%) i/s -    2520297 in   5.004000s

Comparison:
       Hash#each_key:   504252.5 i/s
      Hash#keys.each:   467405.1 i/s - 1.08x slower

$ ruby -v code/hash/fetch-vs-fetch-with-block.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
    Hash#fetch + arg     22940 i/100ms
  Hash#fetch + block     34390 i/100ms
-------------------------------------------------
    Hash#fetch + arg   547418.2 (±6.5%) i/s -    2729860 in   5.010000s
  Hash#fetch + block  1272667.9 (±4.1%) i/s -    6362150 in   5.009000s

Comparison:
  Hash#fetch + block:  1272667.9 i/s
    Hash#fetch + arg:   547418.2 i/s - 2.32x slower

$ ruby -v code/hash/merge-bang-vs-[]=.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
         Hash#merge!      1560 i/100ms
            Hash#[]=      2610 i/100ms
-------------------------------------------------
         Hash#merge!    19429.1 (±6.9%) i/s -      96720 in   5.006000s
            Hash#[]=    29208.1 (±3.6%) i/s -     146160 in   5.011000s

Comparison:
            Hash#[]=:    29208.1 i/s
         Hash#merge!:    19429.1 i/s - 1.50x slower

$ ruby -v code/string/gsub-vs-tr.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
         String#gsub     16487 i/100ms
           String#tr     26737 i/100ms
-------------------------------------------------
         String#gsub   357924.9 (±8.5%) i/s -    1780596 in   5.015000s
           String#tr   702389.7 (±6.9%) i/s -    3502547 in   5.019001s

Comparison:
           String#tr:   702389.7 i/s
         String#gsub:   357924.9 i/s - 1.96x slower

$ ruby -v code/string/casecmp-vs-downcase-==.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
String#downcase + ==     32657 i/100ms
      String#casecmp     37679 i/100ms
-------------------------------------------------
String#downcase + ==  1100758.9 (±5.7%) i/s -    5486376 in   5.002000s
      String#casecmp  1500076.9 (±3.6%) i/s -    7498121 in   5.006000s

Comparison:
      String#casecmp:  1500076.9 i/s
String#downcase + ==:  1100758.9 i/s - 1.36x slower

$ ruby -v code/string/gsub-vs-sub.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
         String#gsub     14555 i/100ms
          String#sub     19108 i/100ms
-------------------------------------------------
         String#gsub   338996.7 (±12.1%) i/s -    1659270 in   5.000000s
          String#sub   477597.0 (±4.2%) i/s -    2388500 in   5.011000s

Comparison:
          String#sub:   477597.0 i/s
         String#gsub:   338996.7 i/s - 1.41x slower

$ ruby -v code/string/concatenation.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
            String#+     38259 i/100ms
       String#concat     35921 i/100ms
       String#append     37821 i/100ms
         "foo" "bar"     47268 i/100ms
-------------------------------------------------
            String#+  1430385.1 (±5.6%) i/s -    7116174 in   4.993000s
       String#concat  1346297.1 (±3.5%) i/s -    6717227 in   4.996000s
       String#append  1312505.8 (±4.5%) i/s -    6543033 in   4.997000s
         "foo" "bar"  2123294.3 (±5.1%) i/s -   10588032 in   5.002000s

Comparison:
         "foo" "bar":  2123294.3 i/s
            String#+:  1430385.1 i/s - 1.48x slower
       String#concat:  1346297.1 i/s - 1.58x slower
       String#append:  1312505.8 i/s - 1.62x slower

$ ruby -v code/string/end-string-checking-match-vs-start_with.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
           String#=~     20095 i/100ms
    String#end_with?     36606 i/100ms
-------------------------------------------------
           String#=~   630058.7 (±7.4%) i/s -    3134820 in   5.007000s
    String#end_with?  1248337.1 (±5.3%) i/s -    6223020 in   5.001000s

Comparison:
    String#end_with?:  1248337.1 i/s
           String#=~:   630058.7 i/s - 1.98x slower

$ ruby -v code/string/start-string-checking-match-vs-start_with.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
           String#=~     25777 i/100ms
  String#start_with?     38710 i/100ms
-------------------------------------------------
           String#=~   722162.8 (±6.7%) i/s -    3583003 in   4.987000s
  String#start_with?  1484014.8 (±2.9%) i/s -    7432320 in   5.013000s

Comparison:
  String#start_with?:  1484014.8 i/s
           String#=~:   722162.8 i/s - 2.05x slower

$ ruby -v code/enumerable/each-vs-for-loop.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
            For loop      6966 i/100ms
               #each      5369 i/100ms
-------------------------------------------------
            For loop    89120.2 (±1.0%) i/s -     445824 in   5.003000s
               #each    69302.0 (±13.7%) i/s -     332878 in   5.029000s

Comparison:
            For loop:    89120.2 i/s
               #each:    69302.0 i/s - 1.29x slower

$ ruby -v code/enumerable/reverse-each-vs-reverse_each.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
  Array#reverse.each      5086 i/100ms
  Array#reverse_each      5465 i/100ms
-------------------------------------------------
  Array#reverse.each    68846.5 (±10.5%) i/s -     335676 in   5.004000s
  Array#reverse_each    73340.8 (±3.6%) i/s -     366155 in   5.000000s

Comparison:
  Array#reverse_each:    73340.8 i/s
  Array#reverse.each:    68846.5 i/s - 1.07x slower

$ ruby -v code/enumerable/each_with_index-vs-while-loop.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
code/enumerable/each_with_index-vs-while-loop.rb:14 warning: Useless use of + in void context.
Calculating -------------------------------------
     each_with_index      3271 i/100ms
          While Loop      3403 i/100ms
-------------------------------------------------
     each_with_index    42730.8 (±7.8%) i/s -     212615 in   5.011000s
          While Loop    37206.3 (±1.0%) i/s -     187165 in   5.031000s

Comparison:
     each_with_index:    42730.8 i/s
          While Loop:    37206.3 i/s - 1.15x slower

$ ruby -v code/enumerable/each-push-vs-map.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
   Array#each + push      2915 i/100ms
           Array#map      5860 i/100ms
-------------------------------------------------
   Array#each + push    38146.8 (±7.6%) i/s -     189475 in   4.999999s
           Array#map    71978.7 (±1.6%) i/s -     363320 in   5.049000s

Comparison:
           Array#map:    71978.7 i/s
   Array#each + push:    38146.8 i/s - 1.89x slower

$ ruby -v code/enumerable/map-flatten-vs-flat_map.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
Array#map.flatten(1)      1273 i/100ms
   Array#map.flatten      1338 i/100ms
      Array#flat_map      3019 i/100ms
-------------------------------------------------
Array#map.flatten(1)    14318.5 (±4.2%) i/s -      72561 in   5.077000s
   Array#map.flatten    14708.3 (±1.8%) i/s -      73590 in   5.005000s
      Array#flat_map    28886.2 (±2.5%) i/s -     144912 in   5.020000s

Comparison:
      Array#flat_map:    28886.2 i/s
   Array#map.flatten:    14708.3 i/s - 1.96x slower
Array#map.flatten(1):    14318.5 i/s - 2.02x slower

$ ruby -v code/enumerable/select-first-vs-detect.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
Enumerable#select.first
                          4491 i/100ms
   Enumerable#detect     17048 i/100ms
-------------------------------------------------
Enumerable#select.first
                        54763.1 (±5.1%) i/s -    1091313 in  19.995999s
   Enumerable#detect   290959.3 (±3.3%) i/s -    5813368 in  20.004000s

Comparison:
   Enumerable#detect:   290959.3 i/s
Enumerable#select.first:    54763.1 i/s - 5.31x slower

$ ruby -v code/enumerable/sort-vs-sort_by.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
     Enumerable#sort       434 i/100ms
  Enumerable#sort_by      1535 i/100ms
-------------------------------------------------
     Enumerable#sort     4820.6 (±6.1%) i/s -      24304 in   5.062000s
  Enumerable#sort_by    16571.7 (±2.7%) i/s -      82890 in   5.006000s

Comparison:
  Enumerable#sort_by:    16571.7 i/s
     Enumerable#sort:     4820.6 i/s - 3.44x slower

$ ruby -v code/array/count-vs-size.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
              #count     38719 i/100ms
               #size     39345 i/100ms
-------------------------------------------------
              #count  1643291.9 (±5.6%) i/s -    8169709 in   4.994000s
               #size  1624987.8 (±5.0%) i/s -    8105070 in   5.003000s

Comparison:
              #count:  1643291.9 i/s
               #size:  1624987.8 i/s - 1.01x slower

$ ruby -v code/array/shuffle-first-vs-sample.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
 Array#shuffle.first      8836 i/100ms
        Array#sample     35388 i/100ms
-------------------------------------------------
 Array#shuffle.first   120878.9 (±3.4%) i/s -     609684 in   5.051000s
        Array#sample  1365647.9 (±7.9%) i/s -    6759108 in   4.992000s

Comparison:
        Array#sample:  1365647.9 i/s
 Array#shuffle.first:   120878.9 i/s - 11.30x slower

$ ruby -v code/array/bsearch-vs-find.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Error: Your application used more memory than the safety cap of 2048M.
Specify -J-Xmx####m to increase it (#### = cap size in MB).
Exception trace follows:
java.lang.OutOfMemoryError: Java heap space
    at org.jruby.RubyFixnum.newFixnum(RubyFixnum.java:186)
    at org.jruby.RubyRange.to_a(RubyRange.java:413)
    at org.jruby.RubyRange$INVOKER$i$0$0$to_a.call(RubyRange$INVOKER$i$0$0$to_a.gen)
    at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodZeroOrNBlock.call(JavaMethod.java:280)
    at org.jruby.RubyClass.finvoke(RubyClass.java:624)
    at org.jruby.runtime.Helpers.invoke(Helpers.java:500)
    at org.jruby.RubyBasicObject.callMethod(RubyBasicObject.java:355)
    at org.jruby.runtime.Helpers.arrayValue(Helpers.java:1808)
    at org.jruby.runtime.Helpers.arrayValue(Helpers.java:1797)
    at org.jruby.runtime.Helpers.splatValue19(Helpers.java:1899)
    at org.jruby.ast.Splat19Node.interpret(Splat19Node.java:48)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RootNode.interpret(RootNode.java:129)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_ROOT(ASTInterpreter.java:121)
    at org.jruby.Ruby.runInterpreter(Ruby.java:893)
    at org.jruby.Ruby.runInterpreter(Ruby.java:901)
    at org.jruby.Ruby.runNormally(Ruby.java:732)
    at org.jruby.Ruby.runFromMain(Ruby.java:577)
    at org.jruby.Main.doRunFromMain(Main.java:395)
    at org.jruby.Main.internalRun(Main.java:290)
    at org.jruby.Main.run(Main.java:217)
    at org.jruby.Main.main(Main.java:197)
$ ruby -v code/proc-and-block/block-vs-to_proc.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
               Block      1906 i/100ms
      Symbol#to_proc      1826 i/100ms
-------------------------------------------------
               Block    26342.2 (±17.9%) i/s -     116266 in   5.039000s
      Symbol#to_proc    40614.6 (±5.1%) i/s -     202686 in   5.005000s

Comparison:
      Symbol#to_proc:    40614.6 i/s
               Block:    26342.2 i/s - 1.54x slower

$ ruby -v code/proc-and-block/proc-call-vs-yield.rb
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 [linux-amd64]
Calculating -------------------------------------
          block.call     29970 i/100ms
               yield     36018 i/100ms
-------------------------------------------------
          block.call  1051319.0 (±8.3%) i/s -    5094900 in   4.987000s
               yield  1191218.5 (±24.2%) i/s -    4826412 in   5.004000s

Comparison:
               yield:  1191218.5 i/s
          block.call:  1051319.0 i/s - 1.13x slower