Why performance difference vs JRuby?

Why is current Ruby (2.3.1) so much slower than current JRuby (9.1.2)?

It’s obviously an implementation differences, but why such a flip flop
in performance from MRI to JRuby?


require ‘benchmark-ips’

a = (1…1000).to_a

Benchmark.ips do |x|
x.report(“block”) { sum=0; a.each {|i| sum += i}; sum }
x.report(“reduce”) { a.reduce(:+) }
x.compare!
end

Results for jruby-9.1.2.0

Warming up --------------------------------------
block 1.056k i/100ms
reduce 2.045k i/100ms
Calculating -------------------------------------
block 12.568k (± 6.1%) i/s - 63.360k in
5.062776s
reduce 21.492k (± 6.6%) i/s - 108.385k in
5.067897s

Comparison:
reduce: 21492.3 i/s
block: 12568.2 i/s - 1.71x slower

Results for ruby-2.3.1

Warming up --------------------------------------
block 1.523k i/100ms
reduce 1.101k i/100ms
Calculating -------------------------------------
block 15.398k (± 5.2%) i/s - 77.673k in
5.059496s
reduce 10.890k (± 4.7%) i/s - 55.050k in
5.067444s

Comparison:
block: 15398.4 i/s
reduce: 10889.9 i/s - 1.41x slower

If you compare current Ruby with earlier Ruby implementations, do you
also see a performance degradation? Did you always use the same JVM now
and in the past when measuring JRuby? A change in the JVM version could
also account for a change in speed.

What platform ?

On x86_64-linux block test is on par, reduce test is faster by 30%.

I’ve added an equivalent block version of reduce test:

  x.report("reduce2") { a.reduce {|m,n| m+n} }

There is CRuby about 5% faster then JRuby in contrast.

CRuby 2.3.1
CRuby 2.1.10
JRuby 9.1.2.0

I think JRuby does some micro-optimization of :+ symbol to_proc variant,
but have no time to confirm by analyzing produced bytecode.

Joan Blackmoore wrote in post #1184635:

What platform ?

In JRuby, the performance depends a lot about the JVM being used, for
one due to various optimizations inside the byte code loader, but also
due to the performance of the garbage collector, which also depends on
the Java version.

Ronald

First a type: require ‘benchmark-ips’
should be: require ‘benchmark/ips’

The results I originally posted were on a 32-bit Linux system.

The results I get on a 64-bit Linux system are:
For cruby 2.3.1 it’s similar to 32-bit, ‘block’ is faster than ‘reduce’.
For jruby 9.1.2.0 they were same-ish with ‘reduce’ a bit faster.
In all cases ‘reduce2’ was slowest.