# module Benchmark

### Public Class Methods

compare(*reports) click to toggle source

    # File lib/benchmark/compare.rb, line 2
    def compare(*reports)
      return if reports.size < 2

      iter = false
      sorted = reports.sort do |a,b|
        if a.respond_to? :ips
          iter = true
          b.ips <=> a.ips
        else
          a.runtime <=> b.runtime
        end
      end

      best = sorted.shift

      STDOUT.puts "\nComparison:"

      if iter
        STDOUT.printf "%20s: %10.1f i/s\n", best.label, best.ips
      else
        STDOUT.puts "#{best.rjust(20)}: #{best.runtime}s"
      end

      sorted.each do |report|
        name = report.label

        if iter
          x = (best.ips.to_f / report.ips.to_f)
          STDOUT.printf "%20s: %10.1f i/s - %.2fx slower\n", name, report.ips, x
        else
          x = "%.2f" % (report.ips.to_f / best.ips.to_f)
          STDOUT.puts "#{name.rjust(20)}: #{report.runtime}s - #{x}x slower"
        end
      end

      STDOUT.puts
    end

ips(time=5, warmup=2) { |job| ... } click to toggle source

    # File lib/benchmark/ips.rb, line 139
    def ips(time=5, warmup=2)
      suite = nil

      sync, $stdout.sync = $stdout.sync, true

      if defined? Benchmark::Suite and Suite.current
        suite = Benchmark::Suite.current
      end

      quiet = suite && !suite.quiet?

      job = IPSJob.new
      yield job

      reports = []

      timing = {}

      $stdout.puts "Calculating -------------------------------------" unless quiet

      job.list.each do |item|
        suite.warming item.label, warmup if suite

        Timing.clean_env

        unless quiet
          if item.label.size > 20
            $stdout.print "#{item.label}\n#{' ' * 20}"
          else
            $stdout.print item.label.rjust(20)
          end
        end

        before = Time.now
        target = Time.now + warmup

        warmup_iter = 0

        while Time.now < target
          item.call_times(1)
          warmup_iter += 1
        end

        after = Time.now

        warmup_time = (after.to_f - before.to_f) * 1_000_000.0

        # calculate the time to run approx 100ms

        cycles_per_100ms = ((100_000 / warmup_time) * warmup_iter).to_i
        cycles_per_100ms = 1 if cycles_per_100ms <= 0

        timing[item] = cycles_per_100ms

        $stdout.printf "%10d i/100ms\n", cycles_per_100ms unless quiet

        suite.warmup_stats warmup_time, cycles_per_100ms if suite
      end

      $stdout.puts "-------------------------------------------------" unless quiet

      job.list.each do |item|
        unless quiet
          if item.label.size > 20
            $stdout.print "#{item.label}\n#{' ' * 20}"
          else
            $stdout.print item.label.rjust(20)
          end
        end

        Timing.clean_env

        suite.running item.label, time if suite

        iter = 0

        target = Time.now + time

        measurements = []

        cycles_per_100ms = timing[item]

        while Time.now < target
          before = Time.now
          item.call_times cycles_per_100ms
          after = Time.now

          # If for some reason the timing said this too no time (O_o)
          # then ignore the iteration entirely and start another.
          #
          m = ((after.to_f - before.to_f) * 1_000_000.0)
          next if m <= 0.0

          iter += cycles_per_100ms

          measurements << m
        end

        measured_us = measurements.inject(0) { |a,i| a + i }

        all_ips = measurements.map { |i| cycles_per_100ms.to_f / (i.to_f / 1_000_000) }

        avg_ips = Timing.mean(all_ips)
        sd_ips =  Timing.stddev(all_ips).round

        rep = IPSReport.new(item.label, measured_us, iter, avg_ips, sd_ips, cycles_per_100ms)

        $stdout.puts " #{rep.body}" unless quiet

        suite.add_report rep, caller(1).first if suite

        reports << rep
      end

      $stdout.sync = sync

      if job.compare
        Benchmark.compare(*reports)
      end

      return reports
    end