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.

···

--
Iñaki Baz Castillo
<ibc@aliax.net>

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

···

On Thu, Jan 13, 2011 at 12:05 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

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?

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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 Castillo <ibc@aliax.net>:

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.

--
Iñaki Baz Castillo
<ibc@aliax.net>

% echo "{}" | parse_tree_show
s(:hash)

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

···

On Jan 13, 2011, at 03:05 , Iñaki Baz Castillo wrote:

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

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

Good point :slight_smile:

Thanks a lot.

···

2011/1/13 Jonas Pfenniger (zimbatm) <jonas@pfenniger.name>:

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.

--
Iñaki Baz Castillo
<ibc@aliax.net>

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

···

--
Posted via http://www.ruby-forum.com/\.