module Benchmark

def bmbm(width = 0) # :yield: job

:yield: job

Benchmark::Tms objects.
#bmbm yields a Benchmark::Job object and returns an array of

sort 1.450000 0.000000 1.450000 ( 1.455963)
sort! 1.460000 0.000000 1.460000 ( 1.458065)
user system total real

-------------------------------- total: 2.890000sec
sort 1.440000 0.000000 1.440000 ( 1.448257)
sort! 1.440000 0.010000 1.450000 ( 1.446833)
Rehearsal -----------------------------------------

Generates:

end
x.report("sort") { array.dup.sort }
x.report("sort!") { array.dup.sort! }
Benchmark.bmbm do |x|

array = (1..1000000).map { rand }

require 'benchmark'

calculate the required label width.
Because #bmbm takes two passes through the tests, it can

collection and other effects.
do, and the results are not guaranteed to be isolated from garbage
timings. In reality, though, there's only so much that #bmbm can
the real timings; the cost of this is not included in the
real. GC.start is executed before the start of each of
runtime environment stable, the second time for
the tests twice, the first time as a rehearsal in order to get the
that run later. #bmbm attempts to minimize this effect by running
earlier encounters different garbage collection overheads than
Sometimes benchmark results are skewed because code executed
def bmbm(width = 0) # :yield: job
  job = Job.new(width)
  yield(job)
  width = job.width + 1
  sync = $stdout.sync
  $stdout.sync = true
  # rehearsal
  puts 'Rehearsal '.ljust(width+CAPTION.length,'-')
  ets = job.list.inject(Tms.new) { |sum,(label,item)|
    print label.ljust(width)
    res = Benchmark.measure(&item)
    print res.format
    sum + res
  }.format("total: %tsec")
  print " #{ets}\n\n".rjust(width+CAPTION.length+2,'-')
  # take
  print ' '*width + CAPTION
  job.list.map { |label,item|
    GC.start
    print label.ljust(width)
    Benchmark.measure(label, &item).tap { |res| print res }
  }
ensure
  $stdout.sync = sync unless sync.nil?
end