about

rss

(cons 'ider 'this)

by Mark McGranaghan


## Benchmark.nbmbm ##

require 'benchmark'

# A pattern for benchmarking that I see a lot:
N = 100_000

Bucket = Struct.new(:a, :b, :c)

puts "N: #{N}\n\n"

Benchmark.bmbm do |x|
  x.report("Hash") do
    N.times do
      h = {}
      h[:a] = "1"; h[:b] = "2"; h[:c] = "3"
      h[:a]; h[:b]; h[:c]; h[:a]; h[:b]; h[:c]
    end
  end
  
  x.report("Struct") do
    N.times do
      b = Bucket.new
      b.a = "1"; b.b = "2"; b.c = "3"
      b.a; b.b; b.c; b.a; b.b; b.c
    end
  end
end

# But it seems lame to keep writting N.times in each block:
module Benchmark
  class JobProxy
    attr_reader :benches
    def report(label, &block)
      (@benches ||= []) << [label, block]
    end
  end
  
  def self.nbmbm(n)
    puts "N: #{n}\n\n"
    
    job_proxy = JobProxy.new
    yield(job_proxy)
    
    bmbm do |x|
      job_proxy.benches.each do |(label, block)|
        x.report(label) do
          n.times(&block)
        end
      end
    end
  end
end

# With this we can write the original benchmark as:
Benchmark.nbmbm(100_000) do |x|
  x.report("Hash") do
    h = {}
    h[:a] = "1"; h[:b] = "2"; h[:c] = "3"
    h[:a]; h[:b]; h[:c]; h[:a]; h[:b]; h[:c]
  end
  
  x.report("Struct") do
    b = Bucket.new
    b.a = "1"; b.b = "2"; b.c = "3"
    b.a; b.b; b.c; b.a; b.b; b.c
  end
end

<<