Intuitively, the latter should be faster than the former. However, I was very surprised when I saw benchmark results:
require 'benchmark/ips'
b = (0..20).to_a;
y = 21;
Benchmark.ips do |x|
x.report('<<') { a = b.dup; a << y }
x.report('+=') { a = b.dup; a += [y] }
x.report('push') { a = b.dup; a.push(y) }
x.report('[]=') { a = b.dup; a[a.size]=y }
x.compare!
end
The result is:
Calculating -------------------------------------
<< 24.978k i/100ms
+= 30.389k i/100ms
push 24.858k i/100ms
[]= 22.306k i/100ms
-------------------------------------------------
<< 493.125k (± 3.2%) i/s - 2.473M
+= 599.830k (± 2.3%) i/s - 3.009M
push 476.374k (± 3.3%) i/s - 2.386M
[]= 470.263k (± 3.8%) i/s - 2.364M
Comparison:
+=: 599830.3 i/s
<<: 493125.2 i/s - 1.22x slower
push: 476374.0 i/s - 1.26x slower
[]=: 470262.8 i/s - 1.28x slower
However, when a colleague of mine independently created his own benchmark, the result was quite the opposite:
Benchmark.ips do |x|
x.report('push') {@a = (0..20).to_a; @a.push(21)}
x.report('<<') {@b = (0..20).to_a; @b << 21}
x.report('+=') {@c = (0..20).to_a; @c += [21]}
x.compare!
end
Result:
Calculating -------------------------------------
push 17.623k i/100ms
<< 18.926k i/100ms
+= 16.079k i/100ms
-------------------------------------------------
push 281.476k (± 4.2%) i/s - 1.410M
<< 288.341k (± 3.6%) i/s - 1.457M
+= 219.774k (± 8.3%) i/s - 1.093M
Comparison:
<<: 288341.4 i/s
push: 281476.3 i/s - 1.02x slower
+=: 219774.1 i/s - 1.31x slower
We also cross-ran our benchmarks and on both our machines his benchmark showed that +=
is noticeably slower than <<
, and mine showed the opposite.
Why is that?
UPD: my Ruby version is Ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin14]; my colleague's is 2.2.2 (Don't know full details, will update the post tomorrow).
UPD2: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin12.0] my teammate's Ruby version.
dup
andto_a
as I see there is a difference between two codes? – Stephenstepheniedup
versusto_a
. Another difference is the use of local variable versus instance variable. Still another difference is the use of the same variablea
versus using different variables@a
,@b
,@c
. Try changing your test code and make it as close as possible to your friend's. Then you would be able to pin down the cause of the difference between your test code and your friend's. – Populara = b.to_a;
instead ofa = b.dup
in your code, then, both results looks same – Stephenstephenie