我已经用河内塔的经典例子测试了递归方法的执行速度。
在Java中比JRuby和Ruby具有不同的盘子编号:
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);
}
}
}
结果是:
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
看起来在java和jruby上运行具有相同的性能。
- 这一切都与JVM有关吗?还是 ruby 只使用机器的单核?
- Ruby 中这种非线性性能损失的原因是什么?
- 红宝石 2 有什么问题?
编辑
添加了 Ruby 2.1.3 的结果,其中包含 { tailcall_optimization: true }。正如您现在所看到的,它比默认的 false 选项更快。
还有一个问题:
- 为什么 Ruby 代码在 jruby(目前加载 ruby 1.9)上的运行速度比在 ruby 2.1.3 上快几倍?Ruby 代码也可以编译并在 jvm 上运行吗?
Ruby 和 JRuby 实现如下:
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
这一切都与JVM有关吗?
这就是你的结果所建议的。 JVM确实对代码进行了大量优化。
还是 Ruby 只使用机器的单核?
您的Java程序似乎也只使用一个内核,因此这无关紧要。
Ruby 中这种非线性性能松散的原因是什么?
Ruby 中的性能看起来与移动所有板所需的工作量成线性关系。 Java的更令人惊讶。
JVM不进行尾部调用优化,因此如果您在代码中执行此操作会很有趣。