我有一个处理大量ID的类。我需要它们在Initialize中,但只会在某些情况下使用它们。
实例化具有600万个ID的数组的对象比使用4个ID的数组实例化对象要慢吗? (在未使用此数据的情况下)
答案 0 :(得分:5)
无论你的阵列有多大。 ruby中的变量是对象的引用。这意味着在两种情况下都会发送指针,但不会将实际数据作为参数发送。
require 'benchmark/ips'
class A
def initialize(arr)
@arr = arr
end
def mutate
@arr[0] = 11 # once this code been launched, it will change original object.
end
end
# Do not create test data in the bench!
big_one = 6_000_000.times.map { |_| rand(10)}
small_one = [1,2,3,4]
Benchmark.ips do |x|
x.report do
A.new(big_one)
end
x.report do
A.new(small_one)
end
x.compare!
end
所以,结果:
Warming up --------------------------------------
125.218k i/100ms
128.972k i/100ms
Calculating -------------------------------------
3.422M (± 0.7%) i/s - 17.155M in 5.014048s
3.485M (± 0.5%) i/s - 17.540M in 5.033405s
注意:你不能在基准测试中使用像#to_a这样的方法,(1..6_000_000)范围转换到数组是一个缓慢的操作,这会对最终得分产生影响。
答案 1 :(得分:0)
是的,这对性能不利。为了证明这一点,我创建了这个测试,在那里我创建了一个带有id的实例变量的类。然后我运行了一个简单的无关方法,为自己添加一个数字。
require 'benchmark/ips'
class TestSize
def initialize(ids)
@ids = ids
end
def simple_task(n)
n + n
end
end
Benchmark.ips do |x|
x.report('4 ids') do
test = TestSize.new((1..4).to_a)
test.simple_task(3)
end
x.report('6 million') do
test = TestSize.new((1..6_000_000).to_a)
test.simple_task(3)
end
x.compare!
end
以下是结果
Warming up --------------------------------------
4 ids 112.545k i/100ms
6 million 1.000 i/100ms
Calculating -------------------------------------
4 ids 1.557M (± 5.0%) i/s - 7.766M in 5.001166s
6 million 5.947 (± 0.0%) i/s - 30.000 in 5.077560s
Comparison:
4 ids: 1557013.9 i/s
6 million: 5.9 i/s - 261822.49x slower
所以你可以看到它慢得多,而且使用的内存要多得多。
我一直使用benchmark-ips来测试这样的想法。 https://github.com/evanphx/benchmark-ips
我正在运行OSX 10.12.6,ruby 2.4.1p111