I have tested recursive method execution speed with classic example of Honoi Tower.
First in Java than JRuby and Ruby with different no. of plates:
package com.example;
public class Hanoi {
public static void main(String[] args) {
int [] plates = {25, 26, 27, 28, 29, 30, 31, 32};
for(int i = 0; i < plates.length; i++){
long start = System.currentTimeMillis();
doTowers(plates[i], 'A', 'B', 'C');
System.out.println(System.currentTimeMillis() - start);
}
}
public static void doTowers(int topN, char from, char inter, char to) {
if (topN == 1) {
//NOP
} else {
doTowers(topN - 1, from, to, inter);
doTowers(topN - 1, inter, from, to);
}
}
}
And results are:
Java(millis) JRuby(sec) Ruby(sec) Ruby(sec) Ruby(sec)
java 7 jruby-1.7.9 jruby-1.7.9 ruby-2.1.3 ruby-2.1.3 {tailcall_optimization: true}
364 0.269 3.395 6.160 5.515
380 0.321 6.288 12.401 11.082
1349 1.173 13.462 25.497 22.661
2328 1.25 25.714 50.223 44.494
4674 4.73 51.159 101.825 89.22
4995 5.014 103.252 200.308 177.034
18633 18.637 208.356 411.667 357.561
19978 20.927 421.86 805.138 711.872
Looks like running on java and jruby has the same performance.
- Is it all about JVM? Or does ruby uses only single core of machine?
- What is the reason for this nonlinear performance loss in Ruby?
- What is wrong with ruby 2?
EDITED
Added results of Ruby 2.1.3 with { tailcall_optimization: true }. As you can see now it faster then with default false option.
And another question:
- Why Ruby code runs times faster on jruby (which currently loads ruby 1.9) than on ruby 2.1.3? Does ruby code compiles as well and runs on jvm?
The Ruby and JRuby implementetion are below:
class Hanoi
def do_towers(top_n, from, inter, to)
if top_n == 1
#NOP
else
do_towers top_n - 1, from, to, inter
do_towers top_n - 1, inter, from, to
end
end
end
[25, 26, 27, 28, 29, 30, 31, 32].each do |plate|
start = Time.now
HanoiRb.new.do_towers plate, 'A', 'B', 'C'
puts Time.now - start
end
JRuby:
include Java
$CLASSPATH << 'lib'
Hanoi = JavaUtilities.get_proxy_class('com.example.Hanoi')
[25, 26, 27, 28, 29, 30, 31, 32].each do |plate|
start = Time.now
Hanoi.doTowers(plate, 'A'.to_java.toCharArray[0], 'B'.to_java.toCharArray[0], 'C'.to_java.toCharArray[0])
puts Time.now - start
end