Hash#merge({}) vs Hash#dup#merge!({}) vs {}#merge!(Hash) by bejmuller · Pull Request #42 · fastruby/fast-ruby

{}#merge!(other) do end is the fastest only when other has only one key.
Every key more means 10% slow down.

ENUM = (1..100)
ORIGINAL_HASH = { foo: { a: 1, b: { c: 3 } }, bar: {}, baz: "baz", ruby: "ruby", test: "test", yup: "yup", rails: "rails" }

def fast
  ENUM.inject([]) do |accumulator, element|
    accumulator << ({ bar: element }.merge!(ORIGINAL_HASH) { |_key, left, _right| left })
  end
end

def slow
  ENUM.inject([]) do |accumulator, element|
    accumulator << ORIGINAL_HASH.merge(bar: element)
  end
end

def slow_dup
  ENUM.inject([]) do |accumulator, element|
    accumulator << ORIGINAL_HASH.dup.merge!(bar: element)
  end
end

Benchmark.ips do |x|
  x.report("{}#merge!(Hash) do end") { fast }
  x.report("Hash#merge({})") { slow }
  x.report("Hash#dup#merge!({})") { slow_dup }
  x.compare!
end

ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-darwin18]
Warming up --------------------------------------
{}#merge!(Hash) do end
                         1.799k i/100ms
      Hash#merge({})     2.956k i/100ms
 Hash#dup#merge!({})     1.217k i/100ms
Calculating -------------------------------------
{}#merge!(Hash) do end
                         18.216k (± 1.7%) i/s -     91.749k in   5.038319s
      Hash#merge({})     29.844k (± 2.9%) i/s -    150.756k in   5.056616s
 Hash#dup#merge!({})     12.288k (± 2.4%) i/s -     62.067k in   5.054204s

Comparison:
      Hash#merge({}):    29844.0 i/s
{}#merge!(Hash) do end:    18215.6 i/s - 1.64x  slower
 Hash#dup#merge!({}):    12287.7 i/s - 2.43x  slower