Bug #10003

Hash#fetch performance issue

Added by Richard Schneeman over 1 year ago. Updated over 1 year ago.

ruby -v:2.1.2 Backport:2.0.0: UNKNOWN, 2.1: UNKNOWN


It looks like there is a performance issue with Hash#fetch compared to Hash#[]. I found this issue via this gist: https://gist.github.com/jonleighton/3552829. I could not find it reported anywhere on the tracker, forgive me if this is a known issue:

require 'benchmark/ips'

h = { foo: :bar }

Benchmark.ips do |r|
  r.report('#[]')    { h[:foo] }
  r.report('#fetch') { h.fetch(:foo) }

Calculating -------------------------------------
                 #[]    124893 i/100ms
              #fetch    121729 i/100ms
                 #[]  6917857.4 (±20.4%) i/s -   32472180 in   5.008832s
              #fetch  4570251.5 (±18.8%) i/s -   22032949 in   5.015712s

This is in Ruby 2.1.2


#1 Updated by Jeremy Evans over 1 year ago

I believe this is expected since the Hash#[] call is optimized to call rb_hash_aref (see opt_aref in insns.def), where the Hash#fetch call goes through normal method dispatch. Array#[] calls are similarly optimized to call rb_ary_entry.

#2 Updated by Eric Wong over 1 year ago

Jeremy is correct, Hash# have optimized dispatch.
I hardly see Hash#fetch used anywhere, and optimizing dispatch for
uncommon cases hurts performance of common cases.

P.S. even if Hash#fetch were optimized, it would still be slower
because it has optional args to parse.

Also available in: Atom PDF