我原以为
对于
在Ruby 2.1.2上运行基准测试时,这些假设不成立。为什么?
代码:
Array#shift
和Array#unshift
的运行时间都应该是Θ(n)
。原因是机器需要遍历每个数组成员并将其分配给左侧或右侧的键。对于
Array#unshift
,假设只传入一个值作为参数,并且有许多数组成员,我认为对array[0]
进行值分配不会对运行时间产生显着影响。换句话说,当数组成员数量很高,而传递到Array#unshift
中的变量数量很少时,我预计Array#shift
和Array#unshift
具有相同的运行时间。在Ruby 2.1.2上运行基准测试时,这些假设不成立。为什么?
代码:
require 'benchmark'
GC.disable
number_of_elements = 25_600_000
a1 =[]
a2 = []
a3 = []
a4 = []
q1 = Queue.new
q2 = Queue.new
puts number_of_elements
number_of_elements.times do
q1.enq(true)
q2.enq(true)
a1 << true
a2 << true
a3 << true
a4 << true
end
number_of_operations = 1
Benchmark.bm do |bm|
puts "Queue#enq('test')"
bm.report do
number_of_operations.times { q1.enq('test') }
end
puts "Queue#deq"
bm.report do
number_of_operations.times { q2.deq }
end
puts "Array#shift"
bm.report do
number_of_operations.times { a1.shift }
end
puts "Array#unshift"
bm.report do
number_of_operations.times { a2.unshift('test') }
end
puts "Array#pop"
bm.report do
number_of_operations.times { a3.pop }
end
puts "Array#<<"
bm.report do
number_of_operations.times { a4 << 'test' }
end
end
结果:
25600000
user system total real
Queue#enq('test')
0.000000 0.000000 0.000000 ( 0.000006)
Queue#deq
0.010000 0.020000 0.030000 ( 0.029928)
Array#shift
0.010000 0.020000 0.030000 ( 0.032203)
Array#unshift
0.080000 0.060000 0.140000 ( 0.143272)
Array#pop
0.000000 0.000000 0.000000 ( 0.000004)
Array#<<
0.000000 0.000000 0.000000 ( 0.000007)
shift
/unshift
的工作原理?幕后可能发生各种事情,这会影响你的结果。向数组开头添加一个元素并不一定为数组分配单个新条目,它可能会分配多个条目,或者只是移动指向数组起始位置的指针;同样,shift
一个元素可能只是更新指针以指向新的索引0地址。 - mu is too short