Why {} is much faster than Hash.new?

Hi, a simple benchmark:

Benchmark.realtime { 1000000.times { @m = Hash.new } }
=> 0.6552023887634277

Benchmark.realtime { 1000000.times { @m = {} } }
=> 0.17668819427490234

I would like to know why {} is so much faster. I can understand that
Hash.initialize method must inspect is an argument is given and so, is
just due to it?

Thanks.

On Thu, Jan 13, 2011 at 12:05 PM, Iaki Baz C. [email protected]
wrote:

just due to it?
I can imagine that’s about right. Another benchmark:

13:10:40 Temp$ ruby19 bm.rb
Rehearsal --------------------------------------------------
Hash.new 1.297000 0.000000 1.297000 ( 1.293000)
Hash 0.125000 0.000000 0.125000 ( 0.127000)
Hash.nil? 0.187000 0.000000 0.187000 ( 0.186000)
{} 0.188000 0.000000 0.188000 ( 0.191000)
----------------------------------------- total: 1.797000sec

                 user     system      total        real

Hash.new 1.296000 0.000000 1.296000 ( 1.292000)
Hash 0.125000 0.000000 0.125000 ( 0.127000)
Hash.nil? 0.188000 0.000000 0.188000 ( 0.185000)
{} 0.187000 0.000000 0.187000 ( 0.191000)
13:10:50 Temp$ cat bm.rb
require ‘benchmark’

R = 1_000_000

Benchmark.bmbm 15 do |b|
b.report “Hash.new” do
R.times { Hash.new }
end

b.report “Hash” do
R.times { Hash }
end

b.report “Hash.nil?” do
R.times { Hash.nil? }
end

b.report “{}” do
R.times { {} }
end
end
13:10:52 Temp$

Cheers

robert

I think it’s the cost of the method call with options parsing.

Benchmark.realtime do 1_000_000.times do @m = Hash.new end end
=> 1.1976041793823242

def blank_method; end
Benchmark.realtime do 1_000_000.times do @m = blank_method end end
=> 0.1965808868408203

Benchmark.realtime do 1_000_000.times do @m = {} end end
=> 0.2893531322479248

Benchmark.realtime do 1_000_000.times do @m = Hash.allocate end end
=> 0.3925323486328125

You see that Hash.allocate’s time is about the same as ({} +
blank_method). The rest comes from option parsing I guess.

2011/1/13 Iñaki Baz C. [email protected]:

2011/1/13 Jonas P. (zimbatm) [email protected]:

=> 0.2893531322479248

Benchmark.realtime do 1_000_000.times do @m = Hash.allocate end end
=> 0.3925323486328125

You see that Hash.allocate’s time is about the same as ({} +
blank_method). The rest comes from option parsing I guess.

Good point :slight_smile:

Thanks a lot.

I think it’s the cost of the method call with options parsing.

You’d think they’d be able to optimize that , if that’s the case…

-r

On Jan 13, 2011, at 03:05 , Iaki Baz C. wrote:

Benchmark.realtime { 1000000.times { @m = Hash.new } }
=> 0.6552023887634277

Benchmark.realtime { 1000000.times { @m = {} } }
=> 0.17668819427490234

% echo “{}” | parse_tree_show
s(:hash)

% echo “Hash.new” | parse_tree_show
s(:call, s(:const, :Hash), :new, s(:arglist))