Skip to content

Instantly share code, notes, and snippets.

@postmodern
Created September 18, 2023 04:04
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 postmodern/3797e1c265bebad952cbe9aef9589d65 to your computer and use it in GitHub Desktop.
Save postmodern/3797e1c265bebad952cbe9aef9589d65 to your computer and use it in GitHub Desktop.
Micro-benchmark to test `||=` and `[]=` vs. explicit initialize xor `[]=`
#!/usr/bin/env ruby
require 'benchmark'
keys = ('aa'..'zz').map(&:to_sym)
Benchmark.bm do |b|
n = 10_000
b.report('lazy initialize') do
n.times do
hash = nil
keys.each do |key|
hash ||= {}
hash[key] = 1
end
end
end
b.report('explicit initialize') do
n.times do
hash = nil
keys.each do |key|
if hash
hash[key] = 1
else
hash = {key => 1}
end
end
end
end
end
@postmodern
Copy link
Author

       user     system      total        real
lazy initialize  0.968563   0.049878   1.018441 (  1.023334)
explicit initialize  0.950206   0.003927   0.954133 (  0.958803)

@sanG-github
Copy link

sanG-github commented Sep 26, 2023

IMHO, it's not fair when comparing that way.

In the lazy initialize part, should we change it to below instead?
(since we need to initialize the hash with the default key rather than an empty hash.)

    n.times do
      hash = nil

      keys.each do |key|
        hash ||= {key: 1}
      end
    end

@fwolfst
Copy link

fwolfst commented Sep 26, 2023

Agree to @sanG-github Nope, that would then only set the very first key.

Alternative:

else # !hash
  hash = {}
  hash[key] = 1
end

In my case, doesnt have much effect on the benchmark results, though.
Quicker implementation in my short tests is

b.report('explicit initialize, always assign') do
    n.times do
      hash = nil

      keys.each do |key|
        if !hash
          hash = {}
        end

        hash[key] = 1
      end
    end
 end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment