public
Rubygem
Fork of Pistos/better-benchmark
Description: Statistically correct benchmarking for Ruby.
Homepage:
Clone URL: git://github.com/jtrupiano/better-benchmark.git
better-benchmark / lib / better-benchmark / better-benchmark.rb
100644 75 lines (65 sloc) 2.187 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
require 'benchmark'
require 'rsruby'
 
module Benchmark
  
  class ComparisonPartial
    def initialize( block, options )
      @block1 = block
      @options = options
    end
    
    def with( &block2 )
      times1 = []
      times2 = []
      
      teardown1 = @options[:teardown1]
      teardown2 = @options[:teardown2]
      (1..@options[ :iterations ]).each do |iteration|
        if @options[ :verbose ]
          $stdout.print "."; $stdout.flush
        end
        
        times1 << Benchmark.realtime { @block1.call( iteration ) }
        teardown1.call if teardown1.respond_to?(:call)
        times2 << Benchmark.realtime { block2.call( iteration ) }
        teardown2.call if teardown2.respond_to?(:call)
      end
      
      r = RSRuby.instance
      wilcox_result = r.wilcox_test( times1, times2 )
  
      {
        :results1 => {
          :times => times1,
          :mean => r.mean( times1 ),
          :stddev => r.sd( times1 ),
        },
        :results2 => {
          :times => times2,
          :mean => r.mean( times2 ),
          :stddev => r.sd( times2 ),
        },
        :p => wilcox_result[ 'p.value' ],
        :W => wilcox_result[ 'statistic' ][ 'W' ],
        :significant => (
          wilcox_result[ 'p.value' ] < @options[ :required_significance ]
        ),
      }
    end
    alias to with
  end
  
  def self.compare_realtime( options = {}, &block1 )
    options[ :iterations ] ||= 20
    options[ :required_significance ] ||= 0.01
    
    ComparisonPartial.new( block1, options )
  end
  
  def self.report_on( result )
    puts
    puts( "Set 1 mean: %.3f s" % [ result[ :results1 ][ :mean ] ] )
    puts( "Set 1 std dev: %.3f" % [ result[ :results1 ][ :stddev ] ] )
    puts( "Set 2 mean: %.3f s" % [ result[ :results2 ][ :mean ] ] )
    puts( "Set 2 std dev: %.3f" % [ result[ :results2 ][ :stddev ] ] )
    puts "p.value: #{result[ :p ]}"
    puts "W: #{result[ :W ]}"
    puts(
      "The difference (%+.1f%%) %s statistically significant." % [
        ( ( result[ :results2 ][ :mean ] - result[ :results1 ][ :mean ] ) / result[ :results1 ][ :mean ] ) * 100,
        result[ :significant ] ? 'IS' : 'IS NOT'
      ]
    )
  end
end