我制作了两个阵列,每个阵列有100万个项目:
a1 = 1_000_000.times.to_a
a2 = a1.clone
Run Code Online (Sandbox Code Playgroud)
我试图将a2推入a1:
a1.push *a2
Run Code Online (Sandbox Code Playgroud)
这回来了SystemStackError: stack level too deep
.
但是,当我尝试使用时concat
,我没有收到错误:
a1.concat a2
a1.length # => 2_000_000
Run Code Online (Sandbox Code Playgroud)
我也没有得到splat运算符的错误:
a3 = [*a1, *a2]
a3.length # => 2_000_000
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我查看了文档Array#push
,并用C语言编写.我怀疑它可能是在引擎盖下进行一些递归,这就是为什么它会导致大型数组的这个错误.它是否正确?push
用于大型阵列不是一个好主意吗?
我想使用ruby ffi gem来调用ac函数,它有一个数组作为输入变量,输出是一个数组.也就是说,c函数看起来像:
double *my_function(double array[], int size)
Run Code Online (Sandbox Code Playgroud)
我创建了ruby绑定:
module MyModule
extend FFI::Library
ffi_lib 'c'
ffi_lib 'my_c_lib'
attach_function :my_function, [:pointer, int], :pointer
Run Code Online (Sandbox Code Playgroud)
我想用ruby代码打电话,如:
result_array = MyModule.my_function([4, 6, 4], 3)
Run Code Online (Sandbox Code Playgroud)
我该怎么做?
虽然做了一些基准来回答这个约来连接阵列我感到惊讶的是,当我在使用JRuby也做了同样的基准测试是慢了很多的最快方法问题.
这是否意味着关于jRuby比MRI Ruby更快的旧的慢板已经消失了?或者这是关于如何在jRuby中处理数组?
这里的基准测试结果和MRI Ruby 2.3.0和jRuby 9.1.2.0两者都运行在64位Windows 7盒子上,所有4个处理器忙于50-60%,内存使用±5.5GB.必须使用参数启动jRuby -J-Xmx1500M
以提供足够的堆空间.由于堆栈级别太深,我不得不使用push删除测试,并且还删除了最慢的方法,使测试时间不长.使用Jave运行时: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, …
Run Code Online (Sandbox Code Playgroud)