Skip to content

Instantly share code, notes, and snippets.

@thiagoa
Created February 14, 2017 10:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thiagoa/929cba80f99aa6f479adecf0d92af63a to your computer and use it in GitHub Desktop.
Save thiagoa/929cba80f99aa6f479adecf0d92af63a to your computer and use it in GitHub Desktop.
require 'benchmark/ips'
require 'active_support/core_ext/hash'
def sample
{ a: 1, b: 2, c: 3, d: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10 }
end
Benchmark.ips do |x|
x.report 'map + to_h' do
h = sample
h.map { |k, v| [k, v + 1] }.to_h
end
x.report 'map + Hash' do
h = sample
Hash[h.map { |k, v| [k, v + 1] }]
end
x.report 'each_with_object' do
h = sample
h.each_with_object({}) do |(k, v), memo|
memo[k] = v + 1
end
end
x.report 'reduce + merge' do
h = sample
h.reduce({}) do |memo, (k, v)|
memo.merge(k => v)
end
end
x.report 'reduce + merge!' do
h = sample
h.reduce({}) do |memo, (k, v)|
memo.merge!(k => v)
end
end
x.report 'reduce + []=' do
h = sample
h.reduce({}) do |memo, (k, v)|
memo[k] = v
memo
end
end
x.report 'transform_values' do
h = sample
h.transform_values { |v| v + 1 }
end
x.report 'each' do
original = sample
h = {}
original.each do |k, v|
h[k] = v + 1
end
end
x.report 'each_key' do
original = sample
h = {}
original.each_key do |k|
h[k] = original[k] + 1
end
end
x.report 'each_key (mutates)' do
h = sample
h.each_key do |k|
h[k] = h[k] + 1
end
end
x.report 'each (mutates)' do
h = sample
h.each do |k, v|
h[k] = v + 1
end
end
x.report 'shift + while (mutates)' do
original = sample
h = {}
while tuple = original.shift
h[tuple[0]] = tuple[1] + 1
end
end
x.report 'transform_values! (m.)' do
h = sample
h.transform_values! { |v| v + 1 }
end
end
# ==== Higher is better ====
#
# - #each is the fastest method and it's my choice for big hashes: 229.897k i/s,
# It still mutates the result array, but the original one is preserved.
# - #each_with_object is usually my choice to perform this task: it has the
# best balance among readability, performance and memory consumption.
# - #transform_values is faster than #each_with_object, but it's not native.
# I'd rarely choose this one due to Active Support.
# - All other non-mutating methods perform lots of unnecessary memory allocations,
# though not reported in this output.
# - "map + to_h" and "map + Hash" are nearly identical, but I still checked if there's
# a difference anyway.
#
# Warming up --------------------------------------
# map + to_h 9.011k i/100ms
# map + Hash 9.215k i/100ms
# each_with_object 10.539k i/100ms
# reduce + merge 3.165k i/100ms
# reduce + merge! 6.104k i/100ms
# reduce + []= 10.659k i/100ms
# transform_values (AS) 9.958k i/100ms
# each 12.531k i/100ms
# each_key 11.185k i/100ms
# each_key (mutates) 18.475k i/100ms
# each (mutates) 19.580k i/100ms
# shift + while (mutates) 11.796k i/100ms
# transform_values! (m.) 16.594k i/100ms
# Calculating -------------------------------------
# map + to_h 95.407k (±10.1%) i/s - 477.583k in 5.044700s
# map + Hash 95.389k (± 8.9%) i/s - 479.180k in 5.055892s
# each_with_object 110.638k (± 9.3%) i/s - 558.567k in 5.084164s
# reduce + merge 30.762k (± 8.6%) i/s - 155.085k in 5.071071s
# reduce + merge! 63.478k (±10.5%) i/s - 317.408k in 5.047015s
# reduce + []= 108.569k (± 8.9%) i/s - 543.609k in 5.041442s
# transform_values 125.668k (±28.9%) i/s - 537.732k in 5.002
# each 146.874k (±27.8%) i/s - 664.143k in 5.064015s
# each_key 141.206k (±19.0%) i/s - 693.470k in 5.079645s
# each_key (mutates) 215.538k (±14.9%) i/s - 1.072M in 5.089780s
# each (mutates) 229.897k (±17.2%) i/s - 1.116M in 5.011291s
# shift + while (mutates) 133.368k (± 8.3%) i/s - 672.372k in 5.072909s
# transform_values! (m.) 187.628k (±12.8%) i/s - 929.264k in 5.037051s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment