Created
October 27, 2014 03:10
-
-
Save danielfone/3607bad04789d43b2676 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require_relative 'micro_bench' | |
| # Various methods to update every value in a hash in place | |
| module HashUpdate | |
| module_function | |
| # also Hash#update | |
| def merge!(hash) | |
| hash.merge!(hash) do |key, value| | |
| value + 1 | |
| end | |
| end | |
| def inject_existing(hash) | |
| hash.inject(hash) do |hash, (key, value)| | |
| hash[key] = value + 1; hash | |
| end | |
| end | |
| def each(hash) | |
| hash.each do |key, value| | |
| hash[key] = value + 1 | |
| end | |
| end | |
| def each_with_object(hash) | |
| hash.each_with_object(hash) do |(key, value), old_hash| | |
| old_hash[key] = value + 1 | |
| end | |
| end | |
| end | |
| # Various methods to map values from one hash to another with identical keys | |
| module HashMap | |
| module_function | |
| def dup_merge(hash) | |
| hash.dup.merge!(hash) do |key, value| | |
| value + 1 | |
| end | |
| end | |
| def merge(hash) | |
| hash.merge(hash) do |key, value| | |
| value + 1 | |
| end | |
| end | |
| def inject_new(hash) | |
| hash.inject({}) do |new_hash, (key, value)| | |
| new_hash[key] = value + 1; new_hash | |
| end | |
| end | |
| def each(hash) | |
| new_hash = {} | |
| hash.each do |key, value| | |
| new_hash[key] = value + 1 | |
| end | |
| new_hash | |
| end | |
| def tap(hash) | |
| {}.tap do |new_hash| | |
| hash.each do |key, value| | |
| new_hash[key] = value + 1 | |
| end | |
| end | |
| end | |
| def each_with_object(hash) | |
| hash.each_with_object({}) do |(key, value), new_hash| | |
| new_hash[key] = value + 1 | |
| end | |
| end | |
| def hash_map(hash) | |
| Hash[hash.map { |k,v| [k,v+1] }] | |
| end | |
| # For the lols | |
| # http://stackoverflow.com/a/13662576/1848 | |
| def map_reduce(hash) | |
| hash.map { |k,v| {k => v+1} }.reduce :merge | |
| end | |
| end | |
| VALUES = Hash[*(1..1000).to_a] | |
| TEST = { | |
| a: 1, | |
| b: 2, | |
| c: 3, | |
| } | |
| RESULT = { | |
| a: 2, | |
| b: 3, | |
| c: 4, | |
| } | |
| b = MicroBench.new HashUpdate, VALUES, TEST => RESULT | |
| b.check *[ | |
| :merge!, | |
| :inject_existing, | |
| :each, | |
| :each_with_object, | |
| ] | |
| b = MicroBench.new HashMap, VALUES, TEST => RESULT | |
| b.check *[ | |
| :merge, | |
| :dup_merge, | |
| :inject_new, | |
| :each, | |
| :hash_map, | |
| # :map_reduce, | |
| :each_with_object, | |
| :tap, | |
| ] | |
| =begin | |
| $ ruby ./update_hash_bench.rb | |
| Testing [:merge!, :inject_existing, :each, :each_with_object]... | |
| all good. | |
| Calculating ------------------------------------- | |
| merge! 1582 i/100ms | |
| inject_existing 941 i/100ms | |
| each 1468 i/100ms | |
| each_with_object 959 i/100ms | |
| ------------------------------------------------- | |
| merge! 16327.9 (±3.1%) i/s - 9492 in 0.581935s | |
| inject_existing 9735.6 (±0.9%) i/s - 5646 in 0.579978s | |
| each 15143.6 (±1.2%) i/s - 8808 in 0.581722s | |
| each_with_object 9682.1 (±1.0%) i/s - 5754 in 0.594349s | |
| Comparison: | |
| merge!: 16327.9 i/s | |
| each: 15143.6 i/s - 1.08x slower | |
| inject_existing: 9735.6 i/s - 1.68x slower | |
| each_with_object: 9682.1 i/s - 1.69x slower | |
| Testing [:merge, :inject_new, :each, :hash_map, :each_with_object, :tap]... | |
| all good. | |
| Calculating ------------------------------------- | |
| merge 399 i/100ms | |
| inject_new 431 i/100ms | |
| each 471 i/100ms | |
| hash_map 385 i/100ms | |
| each_with_object 418 i/100ms | |
| tap 509 i/100ms | |
| ------------------------------------------------- | |
| merge 3985.4 (±22.6%) i/s - 1995 in 0.542334s | |
| inject_new 4194.7 (±4.1%) i/s - 2155 in 0.514623s | |
| each 5835.0 (±33.1%) i/s - 3297 in 0.648399s | |
| hash_map 3863.7 (±6.5%) i/s - 1925 in 0.500590s | |
| each_with_object 4346.3 (±1.0%) i/s - 2508 in 0.577100s | |
| tap 5516.0 (±31.5%) i/s - 3054 in 0.620976s | |
| Comparison: | |
| each: 5835.0 i/s | |
| tap: 5516.0 i/s - 1.06x slower | |
| each_with_object: 4346.3 i/s - 1.34x slower | |
| inject_new: 4194.7 i/s - 1.39x slower | |
| merge: 3985.4 i/s - 1.46x slower | |
| hash_map: 3863.7 i/s - 1.51x slower | |
| =end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The wider distribution on the HashMap benchmarks is due to the object creation triggering GC, disabling will bring that variance down to <10%.