在为回答关于最快地连接数组的这个问题做一些基准测试时,我惊讶地发现在jRuby中进行相同的基准测试时,速度要慢得多。这是否意味着关于jRuby比MRI Ruby更快的古老说法已经不存在了?还是这与jRuby中如何处理数组有关?
这里是基准测试和MRI Ruby 2.3.0和jRuby 9.1.2.0的结果。两者都在64位Windows 7上运行,4个处理器的占用率为50-60%,内存使用量约为5.5GB。必须使用参数
这个问题不涉及使用的不同方法,请参阅原始问题。在这两种情况下,MRI速度快了7倍!有人可以解释一下原因吗?我也很好奇其他实现的情况,比如RBX(Rubinius)。
这里是基准测试和MRI Ruby 2.3.0和jRuby 9.1.2.0的结果。两者都在64位Windows 7上运行,4个处理器的占用率为50-60%,内存使用量约为5.5GB。必须使用参数
-J-Xmx1500M
启动jRuby以提供足够的堆空间。由于堆栈层数太深而不得不删除使用push的测试,并且删除了最慢的方法以使测试时间不要太长。所使用的Java运行时版本为1.7.0_21。require 'Benchmark'
N = 100
class Array
def concat_all
self.reduce([], :+)
end
end
# small arrays
a = (1..10).to_a
b = (11..20).to_a
c = (21..30).to_a
Benchmark.bm do |r|
r.report('plus ') { N.times { a + b + c }}
r.report('concat ') { N.times { [].concat(a).concat(b).concat(c) }}
r.report('splash ') { N.times {[*a, *b, *c]} }
r.report('concat_all ') { N.times { [a, b, c].concat_all }}
r.report('flat_map ') { N.times {[a, b, c].flat_map(&:itself)} }
end
#large arrays
a = (1..10_000_000).to_a
b = (10_000_001..20_000_000).to_a
c = (20_000_001..30_000_000).to_a
Benchmark.bm do |r|
r.report('plus ') { N.times { a + b + c }}
r.report('concat ') { N.times { [].concat(a).concat(b).concat(c) }}
r.report('splash ') { N.times {[*a, *b, *c]} }
r.report('concat_all ') { N.times { [a, b, c].concat_all }}
r.report('flat_map ') { N.times {[a, b, c].flat_map(&:itself)} }
end
这个问题不涉及使用的不同方法,请参阅原始问题。在这两种情况下,MRI速度快了7倍!有人可以解释一下原因吗?我也很好奇其他实现的情况,比如RBX(Rubinius)。
C:\Users\...>d:\jruby\bin\jruby -J-Xmx1500M concat3.rb
user system total real
plus 0.000000 0.000000 0.000000 ( 0.000946)
concat 0.000000 0.000000 0.000000 ( 0.001436)
splash 0.000000 0.000000 0.000000 ( 0.001456)
concat_all 0.000000 0.000000 0.000000 ( 0.002177)
flat_map 0.010000 0.000000 0.010000 ( 0.003179)
user system total real
plus 140.166000 0.000000 140.166000 (140.158687)
concat 143.475000 0.000000 143.475000 (143.473786)
splash 139.408000 0.000000 139.408000 (139.406671)
concat_all 144.475000 0.000000 144.475000 (144.474436)
flat_map143.519000 0.000000 143.519000 (143.517636)
C:\Users\...>ruby concat3.rb
user system total real
plus 0.000000 0.000000 0.000000 ( 0.000074)
concat 0.000000 0.000000 0.000000 ( 0.000065)
splash 0.000000 0.000000 0.000000 ( 0.000098)
concat_all 0.000000 0.000000 0.000000 ( 0.000141)
flat_map 0.000000 0.000000 0.000000 ( 0.000122)
user system total real
plus 15.226000 6.723000 21.949000 ( 21.958854)
concat 11.700000 9.142000 20.842000 ( 20.928087)
splash 21.247000 12.589000 33.836000 ( 33.933170)
concat_all 14.508000 8.315000 22.823000 ( 22.871641)
flat_map 11.170000 8.923000 20.093000 ( 20.170945)
-J-Xmx1500M
。一开始我没有使用这个选项,所以Java使用了默认的最大堆大小(在我的系统上为4096M
),并且工作得很好。如果我提供该选项,将值降低到1500M
,我会得到非常缓慢的结果。 - Stefan