## 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