benchmark-ips-master/0000755000175000017500000000000012150523203015245 5ustar avtobiffavtobiffbenchmark-ips-master/History.txt0000644000175000017500000000007612150523203017452 0ustar avtobiffavtobiff=== 1.0.0 / 2012-03-23 * 1 major enhancement * Birthday! benchmark-ips-master/Manifest.txt0000644000175000017500000000030312150523203017550 0ustar avtobiffavtobiff.autotest History.txt Manifest.txt README.txt Rakefile bin/benchmark_ips lib/benchmark/compare.rb lib/benchmark/helpers.rb lib/benchmark/ips.rb lib/benchmark/timing.rb test/test_benchmark_ips.rb benchmark-ips-master/bin/0000755000175000017500000000000012150523203016015 5ustar avtobiffavtobiffbenchmark-ips-master/bin/benchmark_ips0000755000175000017500000000006212150523203020546 0ustar avtobiffavtobiff#!/usr/bin/env ruby abort "you need to write me" benchmark-ips-master/README.txt0000644000175000017500000000454412150523203016752 0ustar avtobiffavtobiff= benchmark-ips * http://github.com/evanphx/benchmark-ips == DESCRIPTION: A iterations per second enhancement to Benchmark == FEATURES/PROBLEMS: * benchmark/ips - benchmarks a blocks iterations/second. For short snippits of code, ips automatically figures out how many times to run the code to get interesting data. No more guessing at random iteration counts! == SYNOPSIS: require 'benchmark/ips' Benchmark.ips do |x| # Typical mode, runs the block as many times as it can x.report("addition") { 1 + 2 } # To reduce overhead, the number of iterations is passed in # and the block must run the code the specific number of times. # Used for when the workload is very small and any overhead # introduces incorrectable errors. x.report("addition2") do |times| i = 0 while i < times 1 + 2 i += 1 end end # To reduce overhead even more, grafts the code given into # the loop that performs the iterations internally to reduce # overhead. Typically not needed, use the |times| form instead. x.report("addition3", "1 + 2") end == REQUIREMENTS: * None! == INSTALL: * gem install benchmark-ips == DEVELOPERS: After checking out the source, run: $ rake newb This task will install any missing dependencies, run the tests/specs, and generate the RDoc. == LICENSE: (The MIT License) Copyright (c) 2012 Evan Phoenix Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. benchmark-ips-master/lib/0000755000175000017500000000000012150523203016013 5ustar avtobiffavtobiffbenchmark-ips-master/lib/benchmark/0000755000175000017500000000000012150523203017745 5ustar avtobiffavtobiffbenchmark-ips-master/lib/benchmark/helpers.rb0000644000175000017500000000170512150523203021737 0ustar avtobiffavtobiffmodule Benchmark module Helpers def fixnum_max if Object.const_defined?(:RUBY_ENGINE) case RUBY_ENGINE when "ruby" 2 ** (wordsize - 2) - 1 when "rbx" Fixnum::MAX when "jruby" 9223372036854775807 else raise "Maximum Fixnum size now known yet for #{RUBY_ENGINE}" end else 2 ** (wordsize - 2) - 1 end end module_function :fixnum_max def fixnum_min if Object.const_defined?(:RUBY_ENGINE) case RUBY_ENGINE when "ruby" - 2 ** (wordsize - 2) when "rbx" Fixnum::MIN when "jruby" -9223372036854775808 else raise "Maximum Fixnum size now known yet for #{RUBY_ENGINE}" end else - 2 ** (wordsize - 2) end end module_function :fixnum_min def wordsize 8 * 1.size end module_function :wordsize end end benchmark-ips-master/lib/benchmark/timing.rb0000644000175000017500000000142212150523203021560 0ustar avtobiffavtobiffmodule Benchmark module Timing def self.mean(samples) sum = samples.inject(0) { |acc, i| acc + i } sum / samples.size end def self.variance(samples, m=nil) m ||= mean(samples) total = samples.inject(0) { |acc, i| acc + ((i - m) ** 2) } total / samples.size end def self.stddev(samples, m=nil) Math.sqrt variance(samples, m) end def self.resample_mean(samples, resample_times=100) resamples = [] resample_times.times do resample = samples.map { samples[rand(samples.size)] } resamples << Timing.mean(resample) end resamples end def self.clean_env # rbx if GC.respond_to? :run GC.run(true) else GC.start end end end end benchmark-ips-master/lib/benchmark/ips.rb0000644000175000017500000001261212150523203021067 0ustar avtobiffavtobiff# encoding: utf-8 require 'benchmark/timing' require 'benchmark/compare' module Benchmark class IPSReport VERSION = "1.1.0" def initialize(label, us, iters, ips, ips_sd, cycles) @label = label @microseconds = us @iterations = iters @ips = ips @ips_sd = ips_sd @measurement_cycle = cycles end attr_reader :label, :microseconds, :iterations, :ips, :ips_sd, :measurement_cycle def seconds @microseconds.to_f / 1_000_000.0 end def stddev_percentage 100.0 * (@ips_sd.to_f / @ips.to_f) end alias_method :runtime, :seconds def body left = "%10.1f (±%.1f%%) i/s" % [ips, stddev_percentage] left.ljust(20) + (" - %10d in %10.6fs" % [@iterations, runtime]) end def header @label.rjust(20) end def to_s "#{header} #{body}" end def display $stdout.puts to_s end end class IPSJob class Entry def initialize(label, action) @label = label if action.kind_of? String compile action @action = self @as_action = true else unless action.respond_to? :call raise ArgumentError, "invalid action, must respond to #call" end @action = action if action.respond_to? :arity and action.arity > 0 @call_loop = true else @call_loop = false end @as_action = false end end attr_reader :label, :action def as_action? @as_action end def call_times(times) return @action.call(times) if @call_loop act = @action i = 0 while i < times act.call i += 1 end end def compile(str) m = (class << self; self; end) code = <<-CODE def call_times(__total); __i = 0 while __i < __total #{str}; __i += 1 end end CODE m.class_eval code end end def initialize @list = [] @compare = false end attr_reader :compare def compare! @compare = true end # # Registers the given label and block pair in the job list. # def item(label="", str=nil, &blk) # :yield: if blk and str raise ArgumentError, "specify a block and a str, but not both" end action = str || blk raise ArgumentError, "no block or string" unless action @list.push Entry.new(label, action) self end alias_method :report, :item # An array of 2-element arrays, consisting of label and block pairs. attr_reader :list end 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 module_function :ips end benchmark-ips-master/lib/benchmark/compare.rb0000644000175000017500000000155212150523203021723 0ustar avtobiffavtobiffmodule Benchmark 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 module_function :compare end benchmark-ips-master/Rakefile0000644000175000017500000000022112150523203016705 0ustar avtobiffavtobiff# -*- ruby -*- require 'rubygems' require 'hoe' Hoe.spec 'benchmark-ips' do developer('Evan Phoenix', 'evan@phx.io') end # vim: syntax=ruby benchmark-ips-master/.autotest0000644000175000017500000000074012150523203017117 0ustar avtobiffavtobiff# -*- ruby -*- require 'autotest/restart' # Autotest.add_hook :initialize do |at| # at.extra_files << "../some/external/dependency.rb" # # at.libs << ":../some/external" # # at.add_exception 'vendor' # # at.add_mapping(/dependency.rb/) do |f, _| # at.files_matching(/test_.*rb$/) # end # # %w(TestA TestB).each do |klass| # at.extra_class_map[klass] = "test/test_misc.rb" # end # end # Autotest.add_hook :run_command do |at| # system "rake build" # end benchmark-ips-master/test/0000755000175000017500000000000012150523203016224 5ustar avtobiffavtobiffbenchmark-ips-master/test/test_benchmark_ips.rb0000644000175000017500000000073612150523203022423 0ustar avtobiffavtobiffrequire "test/unit" require "benchmark/ips" require "stringio" class TestBenchmarkIPS < Test::Unit::TestCase def setup @old_stdout = $stdout $stdout = StringIO.new end def teardown $stdout = @old_stdout end def test_ips reports = Benchmark.ips(1,1) do |x| x.report("sleep") { sleep(0.25) } end rep = reports.first assert_equal "sleep", rep.label assert_equal 4, rep.iterations assert_in_delta 4.0, rep.ips, 0.2 end end