benchmark-ips 2.7.2 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
 - data/History.txt +35 -0
 - data/Manifest.txt +1 -1
 - data/README.md +18 -8
 - data/lib/benchmark/compare.rb +5 -9
 - data/lib/benchmark/ips.rb +79 -14
 - data/lib/benchmark/ips/job.rb +131 -85
 - data/lib/benchmark/ips/job/entry.rb +33 -15
 - data/lib/benchmark/ips/job/stdout_report.rb +6 -1
 - data/lib/benchmark/ips/report.rb +7 -3
 - data/lib/benchmark/ips/share.rb +3 -1
 - data/lib/benchmark/ips/stats/bootstrap.rb +9 -6
 - data/lib/benchmark/ips/stats/sd.rb +19 -11
 - data/lib/benchmark/ips/stats/stats_metric.rb +21 -0
 - data/test/test_benchmark_ips.rb +60 -0
 - metadata +27 -21
 - data/Gemfile.lock +0 -18
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 5bec7b23527f8a5f331788f9de05073eede35e26bbc5a6b81c05a609d964c0ff
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: aa8ba81457df018d94262d0eb722870d34406204d02a61b0ad1aa398fa2903ff
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 0b8c313bd722fd52229c280d4d566fb9e246b8ae4253a0f508a5b9ca7fffd35cd780cc6c9aa96894733ee87d0df844feae530c10dbf38989cb07367094ce19f3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 037a07ffd3f129a06a68b5c53617379a9c7e3397fc9b02a961c7e7bb9b566f3ad0b423a43b3b5ed3e40f9edfac4f6eed810bc231c8e6d1398afaa65730d62946
         
     | 
    
        data/History.txt
    CHANGED
    
    | 
         @@ -1,3 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            === 2.9.0 / 2021-05-21
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * Features
         
     | 
| 
      
 4 
     | 
    
         
            +
              * Suite can now be set via an accessor
         
     | 
| 
      
 5 
     | 
    
         
            +
              * Default SHARE_URL is now `ips.fastruby.io`, operated by Ombu Labs.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            === 2.8.4 / 2020-12-03
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            * Bug fix
         
     | 
| 
      
 10 
     | 
    
         
            +
              * Fixed hold! when results file does not exist.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            === 2.8.3 / 2020-08-28
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            * Bug fix
         
     | 
| 
      
 15 
     | 
    
         
            +
              * Fixed inaccuracy caused by integer overflows.
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            === 2.8.2 / 2020-05-04
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            * Bug fix
         
     | 
| 
      
 20 
     | 
    
         
            +
              * Fixed problems with Manifest.txt.
         
     | 
| 
      
 21 
     | 
    
         
            +
              * Empty interim results files are ignored.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            === 2.8.0 / 2020-05-01
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            * Feature
         
     | 
| 
      
 26 
     | 
    
         
            +
              * Allow running with empty ips block.
         
     | 
| 
      
 27 
     | 
    
         
            +
              * Added save! method for saving interim results.
         
     | 
| 
      
 28 
     | 
    
         
            +
              * Run more than just 1 cycle during warmup to reduce overhead.
         
     | 
| 
      
 29 
     | 
    
         
            +
              * Optimized Job::Entry hot-path for fairer results on JRuby/TruffleRuby.
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            * Bug fix
         
     | 
| 
      
 32 
     | 
    
         
            +
              * Removed the warmup section if set to 0.
         
     | 
| 
      
 33 
     | 
    
         
            +
              * Added some RDoc docs.
         
     | 
| 
      
 34 
     | 
    
         
            +
              * Added some examples in examples/
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       1 
36 
     | 
    
         
             
            === 2.7.2 / 2016-08-18
         
     | 
| 
       2 
37 
     | 
    
         | 
| 
       3 
38 
     | 
    
         
             
            * 1 bug fix:
         
     | 
    
        data/Manifest.txt
    CHANGED
    
    | 
         @@ -1,5 +1,4 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            .autotest
         
     | 
| 
       2 
     | 
    
         
            -
            Gemfile.lock
         
     | 
| 
       3 
2 
     | 
    
         
             
            History.txt
         
     | 
| 
       4 
3 
     | 
    
         
             
            Manifest.txt
         
     | 
| 
       5 
4 
     | 
    
         
             
            README.md
         
     | 
| 
         @@ -13,5 +12,6 @@ lib/benchmark/ips/report.rb 
     | 
|
| 
       13 
12 
     | 
    
         
             
            lib/benchmark/ips/share.rb
         
     | 
| 
       14 
13 
     | 
    
         
             
            lib/benchmark/ips/stats/bootstrap.rb
         
     | 
| 
       15 
14 
     | 
    
         
             
            lib/benchmark/ips/stats/sd.rb
         
     | 
| 
      
 15 
     | 
    
         
            +
            lib/benchmark/ips/stats/stats_metric.rb
         
     | 
| 
       16 
16 
     | 
    
         
             
            lib/benchmark/timing.rb
         
     | 
| 
       17 
17 
     | 
    
         
             
            test/test_benchmark_ips.rb
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,13 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # benchmark-ips
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * rdoc :: http://rubydoc.info/gems/benchmark-ips
         
     | 
| 
      
 4 
     | 
    
         
            +
            * home :: https://github.com/evanphx/benchmark-ips
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
       1 
6 
     | 
    
         
             
            [](http://badge.fury.io/rb/benchmark-ips)
         
     | 
| 
       2 
7 
     | 
    
         
             
            [](http://travis-ci.org/evanphx/benchmark-ips)
         
     | 
| 
       3 
8 
     | 
    
         
             
            [](http://inch-ci.org/github/evanphx/benchmark-ips)
         
     | 
| 
       4 
9 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            # benchmark-ips
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
10 
     | 
    
         
             
            * https://github.com/evanphx/benchmark-ips
         
     | 
| 
       8 
11 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
            * [documentation](http://rubydoc.info/gems/benchmark-ips)
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
12 
     | 
    
         
             
            ## DESCRIPTION:
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
            An iterations per second enhancement to Benchmark.
         
     | 
| 
         @@ -155,6 +156,11 @@ This will run only one benchmarks each time you run the command, storing 
     | 
|
| 
       155 
156 
     | 
    
         
             
            results in the specified file. The file is deleted when all results have been
         
     | 
| 
       156 
157 
     | 
    
         
             
            gathered and the report is shown.
         
     | 
| 
       157 
158 
     | 
    
         | 
| 
      
 159 
     | 
    
         
            +
            Alternatively, if you prefer a different approach, the `save!` command is
         
     | 
| 
      
 160 
     | 
    
         
            +
            available. Examples for [hold!](examples/hold.rb) and [save!](examples/save.rb) are available in
         
     | 
| 
      
 161 
     | 
    
         
            +
            the `examples/` directory.
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
       158 
164 
     | 
    
         
             
            ### Multiple iterations
         
     | 
| 
       159 
165 
     | 
    
         | 
| 
       160 
166 
     | 
    
         
             
            In some cases you may want to run multiple iterations of the warmup and
         
     | 
| 
         @@ -180,11 +186,15 @@ end 
     | 
|
| 
       180 
186 
     | 
    
         | 
| 
       181 
187 
     | 
    
         
             
            ### Online sharing
         
     | 
| 
       182 
188 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
            If you want to share  
     | 
| 
       184 
     | 
    
         
            -
            with `SHARE=1` argument.  
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
      
 189 
     | 
    
         
            +
            If you want to quickly share your benchmark result with others, run you benchmark
         
     | 
| 
      
 190 
     | 
    
         
            +
            with `SHARE=1` argument. For example: `SHARE=1 ruby my_benchmark.rb`.
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
            Result will be sent to [benchmark.fyi](https://ips.fastruby.io/) and benchmark-ips
         
     | 
| 
       186 
193 
     | 
    
         
             
            will display the link to share the benchmark's result.
         
     | 
| 
       187 
194 
     | 
    
         | 
| 
      
 195 
     | 
    
         
            +
            If you want to run your own instance of [benchmark.fyi](https://github.com/evanphx/benchmark.fyi)
         
     | 
| 
      
 196 
     | 
    
         
            +
            and share it to that instance, you can do this: `SHARE_URL=https://ips.example.com ruby my_benchmark.rb`
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
       188 
198 
     | 
    
         
             
            ### Advanced Statistics
         
     | 
| 
       189 
199 
     | 
    
         | 
| 
       190 
200 
     | 
    
         
             
            By default, the margin of error shown is plus-minus one standard deviation. If
         
     | 
| 
         @@ -221,7 +231,7 @@ Benchmark.ips do |x| 
     | 
|
| 
       221 
231 
     | 
    
         | 
| 
       222 
232 
     | 
    
         
             
              x.stats = :bootstrap
         
     | 
| 
       223 
233 
     | 
    
         
             
              x.confidence = 95
         
     | 
| 
       224 
     | 
    
         
            -
             
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
       225 
235 
     | 
    
         
             
              # confidence is 95% by default, so it can be omitted
         
     | 
| 
       226 
236 
     | 
    
         | 
| 
       227 
237 
     | 
    
         
             
            end
         
     | 
    
        data/lib/benchmark/compare.rb
    CHANGED
    
    | 
         @@ -40,18 +40,14 @@ module Benchmark 
     | 
|
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                  $stdout.puts "\nComparison:"
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                  $stdout.printf "%20s: %10.1f i/s\n", best.label, best.stats.central_tendency
         
     | 
| 
      
 43 
     | 
    
         
            +
                  $stdout.printf "%20s: %10.1f i/s\n", best.label.to_s, best.stats.central_tendency
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
45 
     | 
    
         
             
                  sorted.each do |report|
         
     | 
| 
       46 
46 
     | 
    
         
             
                    name = report.label.to_s
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
       48 
48 
     | 
    
         
             
                    $stdout.printf "%20s: %10.1f i/s - ", name, report.stats.central_tendency
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                     
     | 
| 
       51 
     | 
    
         
            -
                    report_high = report.stats.central_tendency + report.stats.error
         
     | 
| 
       52 
     | 
    
         
            -
                    overlaps = report_high > best_low 
         
     | 
| 
       53 
     | 
    
         
            -
                    
         
     | 
| 
       54 
     | 
    
         
            -
                    if overlaps
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    if report.stats.overlaps?(best.stats)
         
     | 
| 
       55 
51 
     | 
    
         
             
                      $stdout.print "same-ish: difference falls within error"
         
     | 
| 
       56 
52 
     | 
    
         
             
                    else
         
     | 
| 
       57 
53 
     | 
    
         
             
                      slowdown, error = report.stats.slowdown(best.stats)
         
     | 
| 
         @@ -61,7 +57,7 @@ module Benchmark 
     | 
|
| 
       61 
57 
     | 
    
         
             
                      end
         
     | 
| 
       62 
58 
     | 
    
         
             
                      $stdout.print " slower"
         
     | 
| 
       63 
59 
     | 
    
         
             
                    end
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
       65 
61 
     | 
    
         
             
                    $stdout.puts
         
     | 
| 
       66 
62 
     | 
    
         
             
                  end
         
     | 
| 
       67 
63 
     | 
    
         | 
    
        data/lib/benchmark/ips.rb
    CHANGED
    
    | 
         @@ -1,11 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # encoding: utf-8
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'benchmark/timing'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'benchmark/compare'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'benchmark/ips/stats/stats_metric'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'benchmark/ips/stats/sd'
         
     | 
| 
       5 
6 
     | 
    
         
             
            require 'benchmark/ips/stats/bootstrap'
         
     | 
| 
       6 
7 
     | 
    
         
             
            require 'benchmark/ips/report'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'benchmark/ips/noop_suite'
         
     | 
| 
       7 
9 
     | 
    
         
             
            require 'benchmark/ips/job/entry'
         
     | 
| 
       8 
10 
     | 
    
         
             
            require 'benchmark/ips/job/stdout_report'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'benchmark/ips/job/noop_report'
         
     | 
| 
       9 
12 
     | 
    
         
             
            require 'benchmark/ips/job'
         
     | 
| 
       10 
13 
     | 
    
         | 
| 
       11 
14 
     | 
    
         
             
            # Performance benchmarking library
         
     | 
| 
         @@ -15,10 +18,10 @@ module Benchmark 
     | 
|
| 
       15 
18 
     | 
    
         
             
              module IPS
         
     | 
| 
       16 
19 
     | 
    
         | 
| 
       17 
20 
     | 
    
         
             
                # Benchmark-ips Gem version.
         
     | 
| 
       18 
     | 
    
         
            -
                VERSION = "2. 
     | 
| 
      
 21 
     | 
    
         
            +
                VERSION = "2.9.0"
         
     | 
| 
       19 
22 
     | 
    
         | 
| 
       20 
23 
     | 
    
         
             
                # CODENAME of current version.
         
     | 
| 
       21 
     | 
    
         
            -
                CODENAME = " 
     | 
| 
      
 24 
     | 
    
         
            +
                CODENAME = "Sleepy Sasquatch"
         
     | 
| 
       22 
25 
     | 
    
         | 
| 
       23 
26 
     | 
    
         
             
                # Measure code in block, each code's benchmarked result will display in
         
     | 
| 
       24 
27 
     | 
    
         
             
                # iteration per second with standard deviation in given time.
         
     | 
| 
         @@ -32,32 +35,30 @@ module Benchmark 
     | 
|
| 
       32 
35 
     | 
    
         
             
                    time, warmup, quiet = args
         
     | 
| 
       33 
36 
     | 
    
         
             
                  end
         
     | 
| 
       34 
37 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                  suite = nil
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
38 
     | 
    
         
             
                  sync, $stdout.sync = $stdout.sync, true
         
     | 
| 
       38 
39 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                   
     | 
| 
       40 
     | 
    
         
            -
                    suite = Benchmark::Suite.current
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  quiet ||= (suite && suite.quiet?)
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  job = Job.new({:suite => suite,
         
     | 
| 
       46 
     | 
    
         
            -
                                 :quiet => quiet
         
     | 
| 
       47 
     | 
    
         
            -
                  })
         
     | 
| 
      
 40 
     | 
    
         
            +
                  job = Job.new
         
     | 
| 
       48 
41 
     | 
    
         | 
| 
       49 
42 
     | 
    
         
             
                  job_opts = {}
         
     | 
| 
       50 
43 
     | 
    
         
             
                  job_opts[:time] = time unless time.nil?
         
     | 
| 
       51 
44 
     | 
    
         
             
                  job_opts[:warmup] = warmup unless warmup.nil?
         
     | 
| 
      
 45 
     | 
    
         
            +
                  job_opts[:quiet] = quiet unless quiet.nil?
         
     | 
| 
       52 
46 
     | 
    
         | 
| 
       53 
47 
     | 
    
         
             
                  job.config job_opts
         
     | 
| 
       54 
48 
     | 
    
         | 
| 
       55 
49 
     | 
    
         
             
                  yield job
         
     | 
| 
       56 
50 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                  job.load_held_results 
     | 
| 
      
 51 
     | 
    
         
            +
                  job.load_held_results
         
     | 
| 
       58 
52 
     | 
    
         | 
| 
       59 
53 
     | 
    
         
             
                  job.run
         
     | 
| 
       60 
54 
     | 
    
         | 
| 
      
 55 
     | 
    
         
            +
                  if job.run_single? && job.all_results_have_been_run?
         
     | 
| 
      
 56 
     | 
    
         
            +
                    job.clear_held_results
         
     | 
| 
      
 57 
     | 
    
         
            +
                  else
         
     | 
| 
      
 58 
     | 
    
         
            +
                    job.save_held_results
         
     | 
| 
      
 59 
     | 
    
         
            +
                    puts '', 'Pausing here -- run Ruby again to measure the next benchmark...' if job.run_single?
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
       61 
62 
     | 
    
         
             
                  $stdout.sync = sync
         
     | 
| 
       62 
63 
     | 
    
         
             
                  job.run_comparison
         
     | 
| 
       63 
64 
     | 
    
         
             
                  job.generate_json
         
     | 
| 
         @@ -102,4 +103,68 @@ module Benchmark 
     | 
|
| 
       102 
103 
     | 
    
         
             
              end
         
     | 
| 
       103 
104 
     | 
    
         | 
| 
       104 
105 
     | 
    
         
             
              extend Benchmark::IPS # make ips available as module-level method
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
              ##
         
     | 
| 
      
 108 
     | 
    
         
            +
              # :singleton-method: ips
         
     | 
| 
      
 109 
     | 
    
         
            +
              #
         
     | 
| 
      
 110 
     | 
    
         
            +
              #     require 'benchmark/ips'
         
     | 
| 
      
 111 
     | 
    
         
            +
              #
         
     | 
| 
      
 112 
     | 
    
         
            +
              #     Benchmark.ips do |x|
         
     | 
| 
      
 113 
     | 
    
         
            +
              #       # Configure the number of seconds used during
         
     | 
| 
      
 114 
     | 
    
         
            +
              #       # the warmup phase (default 2) and calculation phase (default 5)
         
     | 
| 
      
 115 
     | 
    
         
            +
              #       x.config(:time => 5, :warmup => 2)
         
     | 
| 
      
 116 
     | 
    
         
            +
              #
         
     | 
| 
      
 117 
     | 
    
         
            +
              #       # These parameters can also be configured this way
         
     | 
| 
      
 118 
     | 
    
         
            +
              #       x.time = 5
         
     | 
| 
      
 119 
     | 
    
         
            +
              #       x.warmup = 2
         
     | 
| 
      
 120 
     | 
    
         
            +
              #
         
     | 
| 
      
 121 
     | 
    
         
            +
              #       # Typical mode, runs the block as many times as it can
         
     | 
| 
      
 122 
     | 
    
         
            +
              #       x.report("addition") { 1 + 2 }
         
     | 
| 
      
 123 
     | 
    
         
            +
              #
         
     | 
| 
      
 124 
     | 
    
         
            +
              #       # To reduce overhead, the number of iterations is passed in
         
     | 
| 
      
 125 
     | 
    
         
            +
              #       # and the block must run the code the specific number of times.
         
     | 
| 
      
 126 
     | 
    
         
            +
              #       # Used for when the workload is very small and any overhead
         
     | 
| 
      
 127 
     | 
    
         
            +
              #       # introduces incorrectable errors.
         
     | 
| 
      
 128 
     | 
    
         
            +
              #       x.report("addition2") do |times|
         
     | 
| 
      
 129 
     | 
    
         
            +
              #         i = 0
         
     | 
| 
      
 130 
     | 
    
         
            +
              #         while i < times
         
     | 
| 
      
 131 
     | 
    
         
            +
              #           1 + 2
         
     | 
| 
      
 132 
     | 
    
         
            +
              #           i += 1
         
     | 
| 
      
 133 
     | 
    
         
            +
              #         end
         
     | 
| 
      
 134 
     | 
    
         
            +
              #       end
         
     | 
| 
      
 135 
     | 
    
         
            +
              #
         
     | 
| 
      
 136 
     | 
    
         
            +
              #       # To reduce overhead even more, grafts the code given into
         
     | 
| 
      
 137 
     | 
    
         
            +
              #       # the loop that performs the iterations internally to reduce
         
     | 
| 
      
 138 
     | 
    
         
            +
              #       # overhead. Typically not needed, use the |times| form instead.
         
     | 
| 
      
 139 
     | 
    
         
            +
              #       x.report("addition3", "1 + 2")
         
     | 
| 
      
 140 
     | 
    
         
            +
              #
         
     | 
| 
      
 141 
     | 
    
         
            +
              #       # Really long labels should be formatted correctly
         
     | 
| 
      
 142 
     | 
    
         
            +
              #       x.report("addition-test-long-label") { 1 + 2 }
         
     | 
| 
      
 143 
     | 
    
         
            +
              #
         
     | 
| 
      
 144 
     | 
    
         
            +
              #       # Compare the iterations per second of the various reports!
         
     | 
| 
      
 145 
     | 
    
         
            +
              #       x.compare!
         
     | 
| 
      
 146 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 147 
     | 
    
         
            +
              #
         
     | 
| 
      
 148 
     | 
    
         
            +
              # This will generate the following report:
         
     | 
| 
      
 149 
     | 
    
         
            +
              #
         
     | 
| 
      
 150 
     | 
    
         
            +
              #     Calculating -------------------------------------
         
     | 
| 
      
 151 
     | 
    
         
            +
              #                 addition    71.254k i/100ms
         
     | 
| 
      
 152 
     | 
    
         
            +
              #                addition2    68.658k i/100ms
         
     | 
| 
      
 153 
     | 
    
         
            +
              #                addition3    83.079k i/100ms
         
     | 
| 
      
 154 
     | 
    
         
            +
              #     addition-test-long-label
         
     | 
| 
      
 155 
     | 
    
         
            +
              #                             70.129k i/100ms
         
     | 
| 
      
 156 
     | 
    
         
            +
              #     -------------------------------------------------
         
     | 
| 
      
 157 
     | 
    
         
            +
              #                 addition     4.955M (± 8.7%) i/s -     24.155M
         
     | 
| 
      
 158 
     | 
    
         
            +
              #                addition2    24.011M (± 9.5%) i/s -    114.246M
         
     | 
| 
      
 159 
     | 
    
         
            +
              #                addition3    23.958M (±10.1%) i/s -    115.064M
         
     | 
| 
      
 160 
     | 
    
         
            +
              #     addition-test-long-label
         
     | 
| 
      
 161 
     | 
    
         
            +
              #                              5.014M (± 9.1%) i/s -     24.545M
         
     | 
| 
      
 162 
     | 
    
         
            +
              #
         
     | 
| 
      
 163 
     | 
    
         
            +
              #     Comparison:
         
     | 
| 
      
 164 
     | 
    
         
            +
              #                addition2: 24011974.8 i/s
         
     | 
| 
      
 165 
     | 
    
         
            +
              #                addition3: 23958619.8 i/s - 1.00x slower
         
     | 
| 
      
 166 
     | 
    
         
            +
              #     addition-test-long-label:  5014756.0 i/s - 4.79x slower
         
     | 
| 
      
 167 
     | 
    
         
            +
              #                 addition:  4955278.9 i/s - 4.85x slower
         
     | 
| 
      
 168 
     | 
    
         
            +
              #
         
     | 
| 
      
 169 
     | 
    
         
            +
              # See also Benchmark::IPS
         
     | 
| 
       105 
170 
     | 
    
         
             
            end
         
     | 
    
        data/lib/benchmark/ips/job.rb
    CHANGED
    
    | 
         @@ -9,6 +9,7 @@ module Benchmark 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  # The percentage of the expected runtime to allow
         
     | 
| 
       10 
10 
     | 
    
         
             
                  # before reporting a weird runtime
         
     | 
| 
       11 
11 
     | 
    
         
             
                  MAX_TIME_SKEW = 0.05
         
     | 
| 
      
 12 
     | 
    
         
            +
                  POW_2_30 = 1 << 30
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
                  # Two-element arrays, consisting of label and block pairs.
         
     | 
| 
       14 
15 
     | 
    
         
             
                  # @return [Array<Entry>] list of entries
         
     | 
| 
         @@ -50,19 +51,24 @@ module Benchmark 
     | 
|
| 
       50 
51 
     | 
    
         
             
                  # @return [Integer]
         
     | 
| 
       51 
52 
     | 
    
         
             
                  attr_accessor :confidence
         
     | 
| 
       52 
53 
     | 
    
         | 
| 
      
 54 
     | 
    
         
            +
                  # Silence output
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # @return [Boolean]
         
     | 
| 
      
 56 
     | 
    
         
            +
                  attr_reader :quiet
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  # Suite
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # @return [Benchmark::IPS::NoopSuite]
         
     | 
| 
      
 60 
     | 
    
         
            +
                  attr_reader :suite
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
       53 
62 
     | 
    
         
             
                  # Instantiate the Benchmark::IPS::Job.
         
     | 
| 
       54 
     | 
    
         
            -
                  # @option opts [Benchmark::Suite] (nil) :suite Specify Benchmark::Suite.
         
     | 
| 
       55 
     | 
    
         
            -
                  # @option opts [Boolean] (false) :quiet Suppress the printing of information.
         
     | 
| 
       56 
63 
     | 
    
         
             
                  def initialize opts={}
         
     | 
| 
       57 
     | 
    
         
            -
                    @suite = opts[:suite] || nil
         
     | 
| 
       58 
     | 
    
         
            -
                    @stdout = opts[:quiet] ? nil : StdoutReport.new
         
     | 
| 
       59 
64 
     | 
    
         
             
                    @list = []
         
     | 
| 
       60 
     | 
    
         
            -
                    @ 
     | 
| 
      
 65 
     | 
    
         
            +
                    @run_single = false
         
     | 
| 
       61 
66 
     | 
    
         
             
                    @json_path = false
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @compare = false
         
     | 
| 
       62 
68 
     | 
    
         
             
                    @held_path = nil
         
     | 
| 
       63 
69 
     | 
    
         
             
                    @held_results = nil
         
     | 
| 
       64 
70 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                    @timing =  
     | 
| 
      
 71 
     | 
    
         
            +
                    @timing = Hash.new 1 # default to 1 in case warmup isn't run
         
     | 
| 
       66 
72 
     | 
    
         
             
                    @full_report = Report.new
         
     | 
| 
       67 
73 
     | 
    
         | 
| 
       68 
74 
     | 
    
         
             
                    # Default warmup and calculation time in seconds.
         
     | 
| 
         @@ -86,6 +92,20 @@ module Benchmark 
     | 
|
| 
       86 
92 
     | 
    
         
             
                    @iterations = opts[:iterations] if opts[:iterations]
         
     | 
| 
       87 
93 
     | 
    
         
             
                    @stats = opts[:stats] if opts[:stats]
         
     | 
| 
       88 
94 
     | 
    
         
             
                    @confidence = opts[:confidence] if opts[:confidence]
         
     | 
| 
      
 95 
     | 
    
         
            +
                    self.quiet = opts[:quiet]
         
     | 
| 
      
 96 
     | 
    
         
            +
                    self.suite = opts[:suite]
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  def quiet=(val)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    @stdout = reporter(quiet: val)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  def suite=(suite)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    @suite = suite || Benchmark::IPS::NoopSuite.new
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  def reporter(quiet:)
         
     | 
| 
      
 108 
     | 
    
         
            +
                    quiet ? NoopReport.new : StdoutReport.new
         
     | 
| 
       89 
109 
     | 
    
         
             
                  end
         
     | 
| 
       90 
110 
     | 
    
         | 
| 
       91 
111 
     | 
    
         
             
                  # Return true if job needs to be compared.
         
     | 
| 
         @@ -94,7 +114,7 @@ module Benchmark 
     | 
|
| 
       94 
114 
     | 
    
         
             
                    @compare
         
     | 
| 
       95 
115 
     | 
    
         
             
                  end
         
     | 
| 
       96 
116 
     | 
    
         | 
| 
       97 
     | 
    
         
            -
                  #  
     | 
| 
      
 117 
     | 
    
         
            +
                  # Run comparison utility.
         
     | 
| 
       98 
118 
     | 
    
         
             
                  def compare!
         
     | 
| 
       99 
119 
     | 
    
         
             
                    @compare = true
         
     | 
| 
       100 
120 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -105,9 +125,27 @@ module Benchmark 
     | 
|
| 
       105 
125 
     | 
    
         
             
                    !!@held_path
         
     | 
| 
       106 
126 
     | 
    
         
             
                  end
         
     | 
| 
       107 
127 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
                  #  
     | 
| 
      
 128 
     | 
    
         
            +
                  # Hold after each iteration.
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # @param held_path [String] File name to store hold file.
         
     | 
| 
       109 
130 
     | 
    
         
             
                  def hold!(held_path)
         
     | 
| 
       110 
131 
     | 
    
         
             
                    @held_path = held_path
         
     | 
| 
      
 132 
     | 
    
         
            +
                    @run_single = true
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                  # Save interim results. Similar to hold, but all reports are run
         
     | 
| 
      
 136 
     | 
    
         
            +
                  # The report label must change for each invocation.
         
     | 
| 
      
 137 
     | 
    
         
            +
                  # One way to achieve this is to include the version in the label.
         
     | 
| 
      
 138 
     | 
    
         
            +
                  # @param held_path [String] File name to store hold file.
         
     | 
| 
      
 139 
     | 
    
         
            +
                  def save!(held_path)
         
     | 
| 
      
 140 
     | 
    
         
            +
                    @held_path = held_path
         
     | 
| 
      
 141 
     | 
    
         
            +
                    @run_single = false
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  # Return true if items are to be run one at a time.
         
     | 
| 
      
 145 
     | 
    
         
            +
                  # For the traditional hold, this is true
         
     | 
| 
      
 146 
     | 
    
         
            +
                  # @return [Boolean] Run just a single item?
         
     | 
| 
      
 147 
     | 
    
         
            +
                  def run_single?
         
     | 
| 
      
 148 
     | 
    
         
            +
                    @run_single
         
     | 
| 
       111 
149 
     | 
    
         
             
                  end
         
     | 
| 
       112 
150 
     | 
    
         | 
| 
       113 
151 
     | 
    
         
             
                  # Return true if job needs to generate json.
         
     | 
| 
         @@ -116,7 +154,7 @@ module Benchmark 
     | 
|
| 
       116 
154 
     | 
    
         
             
                    !!@json_path
         
     | 
| 
       117 
155 
     | 
    
         
             
                  end
         
     | 
| 
       118 
156 
     | 
    
         | 
| 
       119 
     | 
    
         
            -
                  #  
     | 
| 
      
 157 
     | 
    
         
            +
                  # Generate json to given path, defaults to "data.json".
         
     | 
| 
       120 
158 
     | 
    
         
             
                  def json!(path="data.json")
         
     | 
| 
       121 
159 
     | 
    
         
             
                    @json_path = path
         
     | 
| 
       122 
160 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -166,86 +204,114 @@ module Benchmark 
     | 
|
| 
       166 
204 
     | 
    
         
             
                  def iterations_per_sec cycles, time_us
         
     | 
| 
       167 
205 
     | 
    
         
             
                    MICROSECONDS_PER_SECOND * (cycles.to_f / time_us.to_f)
         
     | 
| 
       168 
206 
     | 
    
         
             
                  end
         
     | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
       170 
     | 
    
         
            -
                  def held_results?
         
     | 
| 
       171 
     | 
    
         
            -
                    File.exist?(@held_path)
         
     | 
| 
       172 
     | 
    
         
            -
                  end
         
     | 
| 
       173 
     | 
    
         
            -
                  
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
       174 
208 
     | 
    
         
             
                  def load_held_results
         
     | 
| 
      
 209 
     | 
    
         
            +
                    return unless @held_path && File.exist?(@held_path) && !File.zero?(@held_path)
         
     | 
| 
       175 
210 
     | 
    
         
             
                    require "json"
         
     | 
| 
       176 
     | 
    
         
            -
                    @held_results =  
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
                      [result['item'] 
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
      
 211 
     | 
    
         
            +
                    @held_results = {}
         
     | 
| 
      
 212 
     | 
    
         
            +
                    JSON.load(IO.read(@held_path)).each do |result|
         
     | 
| 
      
 213 
     | 
    
         
            +
                      @held_results[result['item']] = result
         
     | 
| 
      
 214 
     | 
    
         
            +
                      create_report(result['item'], result['measured_us'], result['iter'],
         
     | 
| 
      
 215 
     | 
    
         
            +
                                    create_stats(result['samples']), result['cycles'])
         
     | 
| 
      
 216 
     | 
    
         
            +
                    end
         
     | 
| 
      
 217 
     | 
    
         
            +
                  end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  def save_held_results
         
     | 
| 
      
 220 
     | 
    
         
            +
                    return unless @held_path
         
     | 
| 
      
 221 
     | 
    
         
            +
                    require "json"
         
     | 
| 
      
 222 
     | 
    
         
            +
                    data = full_report.entries.map { |e|
         
     | 
| 
      
 223 
     | 
    
         
            +
                      {
         
     | 
| 
      
 224 
     | 
    
         
            +
                        'item' => e.label,
         
     | 
| 
      
 225 
     | 
    
         
            +
                        'measured_us' => e.microseconds,
         
     | 
| 
      
 226 
     | 
    
         
            +
                        'iter' => e.iterations,
         
     | 
| 
      
 227 
     | 
    
         
            +
                        'samples' => e.samples,
         
     | 
| 
      
 228 
     | 
    
         
            +
                        'cycles' => e.measurement_cycle
         
     | 
| 
      
 229 
     | 
    
         
            +
                      }
         
     | 
| 
      
 230 
     | 
    
         
            +
                    }
         
     | 
| 
      
 231 
     | 
    
         
            +
                    IO.write(@held_path, JSON.generate(data) << "\n")
         
     | 
| 
       180 
232 
     | 
    
         
             
                  end
         
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                  def all_results_have_been_run?
         
     | 
| 
      
 235 
     | 
    
         
            +
                    @full_report.entries.size == @list.size
         
     | 
| 
      
 236 
     | 
    
         
            +
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  def clear_held_results
         
     | 
| 
      
 239 
     | 
    
         
            +
                    File.delete @held_path if File.exist?(@held_path)
         
     | 
| 
      
 240 
     | 
    
         
            +
                  end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
       182 
242 
     | 
    
         
             
                  def run
         
     | 
| 
       183 
     | 
    
         
            -
                    @ 
     | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
       185 
     | 
    
         
            -
                       
     | 
| 
      
 243 
     | 
    
         
            +
                    if @warmup && @warmup != 0 then
         
     | 
| 
      
 244 
     | 
    
         
            +
                      @stdout.start_warming
         
     | 
| 
      
 245 
     | 
    
         
            +
                      @iterations.times do
         
     | 
| 
      
 246 
     | 
    
         
            +
                        run_warmup
         
     | 
| 
      
 247 
     | 
    
         
            +
                      end
         
     | 
| 
       186 
248 
     | 
    
         
             
                    end
         
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
                    @stdout.start_running 
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
                    held = nil
         
     | 
| 
       191 
     | 
    
         
            -
                    
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
                    @stdout.start_running
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
       192 
252 
     | 
    
         
             
                    @iterations.times do |n|
         
     | 
| 
       193 
     | 
    
         
            -
                       
     | 
| 
      
 253 
     | 
    
         
            +
                      run_benchmark
         
     | 
| 
       194 
254 
     | 
    
         
             
                    end
         
     | 
| 
       195 
255 
     | 
    
         | 
| 
       196 
     | 
    
         
            -
                    @stdout.footer 
     | 
| 
       197 
     | 
    
         
            -
                    
         
     | 
| 
       198 
     | 
    
         
            -
                    if held
         
     | 
| 
       199 
     | 
    
         
            -
                      puts
         
     | 
| 
       200 
     | 
    
         
            -
                      puts 'Pausing here -- run Ruby again to measure the next benchmark...'
         
     | 
| 
       201 
     | 
    
         
            -
                    end
         
     | 
| 
      
 256 
     | 
    
         
            +
                    @stdout.footer
         
     | 
| 
       202 
257 
     | 
    
         
             
                  end
         
     | 
| 
       203 
258 
     | 
    
         | 
| 
       204 
259 
     | 
    
         
             
                  # Run warmup.
         
     | 
| 
       205 
260 
     | 
    
         
             
                  def run_warmup
         
     | 
| 
       206 
261 
     | 
    
         
             
                    @list.each do |item|
         
     | 
| 
       207 
     | 
    
         
            -
                      next if  
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
                      @suite.warming item.label, @warmup 
     | 
| 
       210 
     | 
    
         
            -
                      @stdout.warming item.label, @warmup 
     | 
| 
      
 262 
     | 
    
         
            +
                      next if run_single? && @held_results && @held_results.key?(item.label)
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                      @suite.warming item.label, @warmup
         
     | 
| 
      
 265 
     | 
    
         
            +
                      @stdout.warming item.label, @warmup
         
     | 
| 
       211 
266 
     | 
    
         | 
| 
       212 
267 
     | 
    
         
             
                      Timing.clean_env
         
     | 
| 
       213 
268 
     | 
    
         | 
| 
      
 269 
     | 
    
         
            +
                      # Run for up to half of the configured warmup time with an increasing
         
     | 
| 
      
 270 
     | 
    
         
            +
                      # number of cycles to reduce overhead and improve accuracy.
         
     | 
| 
      
 271 
     | 
    
         
            +
                      # This also avoids running with a constant number of cycles, which a
         
     | 
| 
      
 272 
     | 
    
         
            +
                      # JIT might speculate on and then have to recompile in #run_benchmark.
         
     | 
| 
       214 
273 
     | 
    
         
             
                      before = Timing.now
         
     | 
| 
       215 
     | 
    
         
            -
                      target = Timing.add_second before, @warmup
         
     | 
| 
      
 274 
     | 
    
         
            +
                      target = Timing.add_second before, @warmup / 2.0
         
     | 
| 
       216 
275 
     | 
    
         | 
| 
       217 
     | 
    
         
            -
                       
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
                       
     | 
| 
       220 
     | 
    
         
            -
             
     | 
| 
       221 
     | 
    
         
            -
                         
     | 
| 
      
 276 
     | 
    
         
            +
                      cycles = 1
         
     | 
| 
      
 277 
     | 
    
         
            +
                      warmup_iter = 1
         
     | 
| 
      
 278 
     | 
    
         
            +
                      warmup_time_us = 0.0
         
     | 
| 
      
 279 
     | 
    
         
            +
                      while Timing.now + warmup_time_us * 2 < target
         
     | 
| 
      
 280 
     | 
    
         
            +
                        t0 = Timing.now
         
     | 
| 
      
 281 
     | 
    
         
            +
                        item.call_times cycles
         
     | 
| 
      
 282 
     | 
    
         
            +
                        t1 = Timing.now
         
     | 
| 
      
 283 
     | 
    
         
            +
                        warmup_iter = cycles
         
     | 
| 
      
 284 
     | 
    
         
            +
                        warmup_time_us = Timing.time_us(t0, t1)
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                        # If the number of cycles would go outside the 32-bit signed integers range
         
     | 
| 
      
 287 
     | 
    
         
            +
                        # then exit the loop to avoid overflows and start the 100ms warmup runs
         
     | 
| 
      
 288 
     | 
    
         
            +
                        break if cycles >= POW_2_30
         
     | 
| 
      
 289 
     | 
    
         
            +
                        cycles *= 2
         
     | 
| 
       222 
290 
     | 
    
         
             
                      end
         
     | 
| 
       223 
291 
     | 
    
         | 
| 
       224 
     | 
    
         
            -
                       
     | 
| 
      
 292 
     | 
    
         
            +
                      cycles = cycles_per_100ms warmup_time_us, warmup_iter
         
     | 
| 
      
 293 
     | 
    
         
            +
                      @timing[item] = cycles
         
     | 
| 
       225 
294 
     | 
    
         | 
| 
       226 
     | 
    
         
            -
                       
     | 
| 
      
 295 
     | 
    
         
            +
                      # Run for the remaining of warmup in a similar way as #run_benchmark.
         
     | 
| 
      
 296 
     | 
    
         
            +
                      target = Timing.add_second before, @warmup
         
     | 
| 
      
 297 
     | 
    
         
            +
                      while Timing.now + MICROSECONDS_PER_100MS < target
         
     | 
| 
      
 298 
     | 
    
         
            +
                        item.call_times cycles
         
     | 
| 
      
 299 
     | 
    
         
            +
                      end
         
     | 
| 
       227 
300 
     | 
    
         | 
| 
       228 
     | 
    
         
            -
                      @timing[item] 
     | 
| 
      
 301 
     | 
    
         
            +
                      @stdout.warmup_stats warmup_time_us, @timing[item]
         
     | 
| 
      
 302 
     | 
    
         
            +
                      @suite.warmup_stats warmup_time_us, @timing[item]
         
     | 
| 
       229 
303 
     | 
    
         | 
| 
       230 
     | 
    
         
            -
                       
     | 
| 
       231 
     | 
    
         
            -
                      @suite.warmup_stats warmup_time_us, @timing[item] if @suite
         
     | 
| 
       232 
     | 
    
         
            -
                      
         
     | 
| 
       233 
     | 
    
         
            -
                      break if hold?
         
     | 
| 
      
 304 
     | 
    
         
            +
                      break if run_single?
         
     | 
| 
       234 
305 
     | 
    
         
             
                    end
         
     | 
| 
       235 
306 
     | 
    
         
             
                  end
         
     | 
| 
       236 
307 
     | 
    
         | 
| 
       237 
308 
     | 
    
         
             
                  # Run calculation.
         
     | 
| 
       238 
309 
     | 
    
         
             
                  def run_benchmark
         
     | 
| 
       239 
310 
     | 
    
         
             
                    @list.each do |item|
         
     | 
| 
       240 
     | 
    
         
            -
                      if  
     | 
| 
       241 
     | 
    
         
            -
             
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
             
     | 
| 
       244 
     | 
    
         
            -
                        next
         
     | 
| 
       245 
     | 
    
         
            -
                      end
         
     | 
| 
       246 
     | 
    
         
            -
                      
         
     | 
| 
       247 
     | 
    
         
            -
                      @suite.running item.label, @time if @suite
         
     | 
| 
       248 
     | 
    
         
            -
                      @stdout.running item.label, @time if @stdout
         
     | 
| 
      
 311 
     | 
    
         
            +
                      next if run_single? && @held_results && @held_results.key?(item.label)
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
      
 313 
     | 
    
         
            +
                      @suite.running item.label, @time
         
     | 
| 
      
 314 
     | 
    
         
            +
                      @stdout.running item.label, @time
         
     | 
| 
       249 
315 
     | 
    
         | 
| 
       250 
316 
     | 
    
         
             
                      Timing.clean_env
         
     | 
| 
       251 
317 
     | 
    
         | 
| 
         @@ -257,7 +323,7 @@ module Benchmark 
     | 
|
| 
       257 
323 
     | 
    
         
             
                      cycles = @timing[item]
         
     | 
| 
       258 
324 
     | 
    
         | 
| 
       259 
325 
     | 
    
         
             
                      target = Timing.add_second Timing.now, @time
         
     | 
| 
       260 
     | 
    
         
            -
             
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
       261 
327 
     | 
    
         
             
                      while (before = Timing.now) < target
         
     | 
| 
       262 
328 
     | 
    
         
             
                        item.call_times cycles
         
     | 
| 
       263 
329 
     | 
    
         
             
                        after = Timing.now
         
     | 
| 
         @@ -286,31 +352,11 @@ module Benchmark 
     | 
|
| 
       286 
352 
     | 
    
         
             
                        rep.show_total_time!
         
     | 
| 
       287 
353 
     | 
    
         
             
                      end
         
     | 
| 
       288 
354 
     | 
    
         | 
| 
       289 
     | 
    
         
            -
                      @stdout.add_report rep, caller(1).first 
     | 
| 
       290 
     | 
    
         
            -
                      @suite.add_report rep, caller(1).first 
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
       292 
     | 
    
         
            -
                      if  
     | 
| 
       293 
     | 
    
         
            -
                        File.open @held_path, "a" do |f|
         
     | 
| 
       294 
     | 
    
         
            -
                          require "json"
         
     | 
| 
       295 
     | 
    
         
            -
                          f.write JSON.generate({
         
     | 
| 
       296 
     | 
    
         
            -
                            :item => item.label,
         
     | 
| 
       297 
     | 
    
         
            -
                            :measured_us => measured_us,
         
     | 
| 
       298 
     | 
    
         
            -
                            :iter => iter,
         
     | 
| 
       299 
     | 
    
         
            -
                            :samples => samples,
         
     | 
| 
       300 
     | 
    
         
            -
                            :cycles => cycles
         
     | 
| 
       301 
     | 
    
         
            -
                          })
         
     | 
| 
       302 
     | 
    
         
            -
                          f.write "\n"
         
     | 
| 
       303 
     | 
    
         
            -
                        end
         
     | 
| 
       304 
     | 
    
         
            -
                        
         
     | 
| 
       305 
     | 
    
         
            -
                        return true
         
     | 
| 
       306 
     | 
    
         
            -
                      end
         
     | 
| 
       307 
     | 
    
         
            -
                    end
         
     | 
| 
       308 
     | 
    
         
            -
                    
         
     | 
| 
       309 
     | 
    
         
            -
                    if hold? && @full_report.entries.size == @list.size
         
     | 
| 
       310 
     | 
    
         
            -
                      File.delete @held_path if File.exist?(@held_path)
         
     | 
| 
      
 355 
     | 
    
         
            +
                      @stdout.add_report rep, caller(1).first
         
     | 
| 
      
 356 
     | 
    
         
            +
                      @suite.add_report rep, caller(1).first
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
      
 358 
     | 
    
         
            +
                      break if run_single?
         
     | 
| 
       311 
359 
     | 
    
         
             
                    end
         
     | 
| 
       312 
     | 
    
         
            -
                    
         
     | 
| 
       313 
     | 
    
         
            -
                    false
         
     | 
| 
       314 
360 
     | 
    
         
             
                  end
         
     | 
| 
       315 
361 
     | 
    
         | 
| 
       316 
362 
     | 
    
         
             
                  def create_stats(samples)
         
     | 
| 
         @@ -11,10 +11,12 @@ module Benchmark 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    def initialize(label, action)
         
     | 
| 
       12 
12 
     | 
    
         
             
                      @label = label
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
      
 14 
     | 
    
         
            +
                      # We define #call_times on the singleton class of each Entry instance.
         
     | 
| 
      
 15 
     | 
    
         
            +
                      # That way, there is no polymorphism for `@action.call` inside #call_times.
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
       14 
17 
     | 
    
         
             
                      if action.kind_of? String
         
     | 
| 
       15 
     | 
    
         
            -
                         
     | 
| 
      
 18 
     | 
    
         
            +
                        compile_string action
         
     | 
| 
       16 
19 
     | 
    
         
             
                        @action = self
         
     | 
| 
       17 
     | 
    
         
            -
                        @as_action = true
         
     | 
| 
       18 
20 
     | 
    
         
             
                      else
         
     | 
| 
       19 
21 
     | 
    
         
             
                        unless action.respond_to? :call
         
     | 
| 
       20 
22 
     | 
    
         
             
                          raise ArgumentError, "invalid action, must respond to #call"
         
     | 
| 
         @@ -23,12 +25,10 @@ module Benchmark 
     | 
|
| 
       23 
25 
     | 
    
         
             
                        @action = action
         
     | 
| 
       24 
26 
     | 
    
         | 
| 
       25 
27 
     | 
    
         
             
                        if action.respond_to? :arity and action.arity > 0
         
     | 
| 
       26 
     | 
    
         
            -
                           
     | 
| 
      
 28 
     | 
    
         
            +
                          compile_block_with_manual_loop
         
     | 
| 
       27 
29 
     | 
    
         
             
                        else
         
     | 
| 
       28 
     | 
    
         
            -
                           
     | 
| 
      
 30 
     | 
    
         
            +
                          compile_block
         
     | 
| 
       29 
31 
     | 
    
         
             
                        end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                        @as_action = false
         
     | 
| 
       32 
32 
     | 
    
         
             
                      end
         
     | 
| 
       33 
33 
     | 
    
         
             
                    end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
         @@ -40,25 +40,43 @@ module Benchmark 
     | 
|
| 
       40 
40 
     | 
    
         
             
                    # @return [String, Proc] Code to be called, could be String / Proc.
         
     | 
| 
       41 
41 
     | 
    
         
             
                    attr_reader :action
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                    # Call action by given times 
     | 
| 
      
 43 
     | 
    
         
            +
                    # Call action by given times.
         
     | 
| 
       44 
44 
     | 
    
         
             
                    # @param times [Integer] Times to call +@action+.
         
     | 
| 
       45 
45 
     | 
    
         
             
                    # @return [Integer] Number of times the +@action+ has been called.
         
     | 
| 
       46 
46 
     | 
    
         
             
                    def call_times(times)
         
     | 
| 
       47 
     | 
    
         
            -
                       
     | 
| 
      
 47 
     | 
    
         
            +
                      raise '#call_times should be redefined per Benchmark::IPS::Job::Entry instance'
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 50 
     | 
    
         
            +
                    def compile_block
         
     | 
| 
      
 51 
     | 
    
         
            +
                      m = (class << self; self; end)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      code = <<-CODE
         
     | 
| 
      
 53 
     | 
    
         
            +
                        def call_times(times)
         
     | 
| 
      
 54 
     | 
    
         
            +
                          act = @action
         
     | 
| 
       50 
55 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
      
 56 
     | 
    
         
            +
                          i = 0
         
     | 
| 
      
 57 
     | 
    
         
            +
                          while i < times
         
     | 
| 
      
 58 
     | 
    
         
            +
                            act.call
         
     | 
| 
      
 59 
     | 
    
         
            +
                            i += 1
         
     | 
| 
      
 60 
     | 
    
         
            +
                          end
         
     | 
| 
      
 61 
     | 
    
         
            +
                        end
         
     | 
| 
      
 62 
     | 
    
         
            +
                      CODE
         
     | 
| 
      
 63 
     | 
    
         
            +
                      m.class_eval code
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    def compile_block_with_manual_loop
         
     | 
| 
      
 67 
     | 
    
         
            +
                      m = (class << self; self; end)
         
     | 
| 
      
 68 
     | 
    
         
            +
                      code = <<-CODE
         
     | 
| 
      
 69 
     | 
    
         
            +
                        def call_times(times)
         
     | 
| 
      
 70 
     | 
    
         
            +
                          @action.call(times)
         
     | 
| 
      
 71 
     | 
    
         
            +
                        end
         
     | 
| 
      
 72 
     | 
    
         
            +
                      CODE
         
     | 
| 
      
 73 
     | 
    
         
            +
                      m.class_eval code
         
     | 
| 
       56 
74 
     | 
    
         
             
                    end
         
     | 
| 
       57 
75 
     | 
    
         | 
| 
       58 
76 
     | 
    
         
             
                    # Compile code into +call_times+ method.
         
     | 
| 
       59 
77 
     | 
    
         
             
                    # @param str [String] Code to be compiled.
         
     | 
| 
       60 
78 
     | 
    
         
             
                    # @return [Symbol] :call_times.
         
     | 
| 
       61 
     | 
    
         
            -
                    def  
     | 
| 
      
 79 
     | 
    
         
            +
                    def compile_string(str)
         
     | 
| 
       62 
80 
     | 
    
         
             
                      m = (class << self; self; end)
         
     | 
| 
       63 
81 
     | 
    
         
             
                      code = <<-CODE
         
     | 
| 
       64 
82 
     | 
    
         
             
                        def call_times(__total);
         
     | 
| 
         @@ -2,10 +2,14 @@ module Benchmark 
     | 
|
| 
       2 
2 
     | 
    
         
             
              module IPS
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Job
         
     | 
| 
       4 
4 
     | 
    
         
             
                  class StdoutReport
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def initialize
         
     | 
| 
      
 6 
     | 
    
         
            +
                      @last_item = nil
         
     | 
| 
      
 7 
     | 
    
         
            +
                    end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       5 
9 
     | 
    
         
             
                    def start_warming
         
     | 
| 
       6 
10 
     | 
    
         
             
                      $stdout.puts "Warming up --------------------------------------"
         
     | 
| 
       7 
11 
     | 
    
         
             
                    end
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       9 
13 
     | 
    
         
             
                    def start_running
         
     | 
| 
       10 
14 
     | 
    
         
             
                      $stdout.puts "Calculating -------------------------------------"
         
     | 
| 
       11 
15 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -31,6 +35,7 @@ module Benchmark 
     | 
|
| 
       31 
35 
     | 
    
         
             
                    end
         
     | 
| 
       32 
36 
     | 
    
         | 
| 
       33 
37 
     | 
    
         
             
                    def footer
         
     | 
| 
      
 38 
     | 
    
         
            +
                      return unless @last_item
         
     | 
| 
       34 
39 
     | 
    
         
             
                      footer = @last_item.stats.footer
         
     | 
| 
       35 
40 
     | 
    
         
             
                      $stdout.puts footer.rjust(40) if footer
         
     | 
| 
       36 
41 
     | 
    
         
             
                    end
         
     | 
    
        data/lib/benchmark/ips/report.rb
    CHANGED
    
    | 
         @@ -52,6 +52,10 @@ module Benchmark 
     | 
|
| 
       52 
52 
     | 
    
         
             
                      @stats.error
         
     | 
| 
       53 
53 
     | 
    
         
             
                    end
         
     | 
| 
       54 
54 
     | 
    
         | 
| 
      
 55 
     | 
    
         
            +
                    def samples
         
     | 
| 
      
 56 
     | 
    
         
            +
                      @stats.samples
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
       55 
59 
     | 
    
         
             
                    # Number of Cycles.
         
     | 
| 
       56 
60 
     | 
    
         
             
                    # @return [Integer] number of cycles.
         
     | 
| 
       57 
61 
     | 
    
         
             
                    attr_reader :measurement_cycle
         
     | 
| 
         @@ -72,7 +76,7 @@ module Benchmark 
     | 
|
| 
       72 
76 
     | 
    
         
             
                    # Return entry's standard deviation of iteration per second in percentage.
         
     | 
| 
       73 
77 
     | 
    
         
             
                    # @return [Float] +@ips_sd+ in percentage.
         
     | 
| 
       74 
78 
     | 
    
         
             
                    def error_percentage
         
     | 
| 
       75 
     | 
    
         
            -
                       
     | 
| 
      
 79 
     | 
    
         
            +
                      @stats.error_percentage
         
     | 
| 
       76 
80 
     | 
    
         
             
                    end
         
     | 
| 
       77 
81 
     | 
    
         | 
| 
       78 
82 
     | 
    
         
             
                    alias_method :runtime, :seconds
         
     | 
| 
         @@ -84,7 +88,7 @@ module Benchmark 
     | 
|
| 
       84 
88 
     | 
    
         
             
                    def body
         
     | 
| 
       85 
89 
     | 
    
         
             
                      case Benchmark::IPS.options[:format]
         
     | 
| 
       86 
90 
     | 
    
         
             
                      when :human
         
     | 
| 
       87 
     | 
    
         
            -
                        left = "%s (±%4.1f%%) i/s" % [Helpers.scale(@stats.central_tendency), error_percentage]
         
     | 
| 
      
 91 
     | 
    
         
            +
                        left = "%s (±%4.1f%%) i/s" % [Helpers.scale(@stats.central_tendency), @stats.error_percentage]
         
     | 
| 
       88 
92 
     | 
    
         
             
                        iters = Helpers.scale(@iterations)
         
     | 
| 
       89 
93 
     | 
    
         | 
| 
       90 
94 
     | 
    
         
             
                        if @show_total_time
         
     | 
| 
         @@ -93,7 +97,7 @@ module Benchmark 
     | 
|
| 
       93 
97 
     | 
    
         
             
                          left.ljust(20) + (" - %s" % iters)
         
     | 
| 
       94 
98 
     | 
    
         
             
                        end
         
     | 
| 
       95 
99 
     | 
    
         
             
                      else
         
     | 
| 
       96 
     | 
    
         
            -
                        left = "%10.1f (±%.1f%%) i/s" % [@stats.central_tendency, error_percentage]
         
     | 
| 
      
 100 
     | 
    
         
            +
                        left = "%10.1f (±%.1f%%) i/s" % [@stats.central_tendency, @stats.error_percentage]
         
     | 
| 
       97 
101 
     | 
    
         | 
| 
       98 
102 
     | 
    
         
             
                        if @show_total_time
         
     | 
| 
       99 
103 
     | 
    
         
             
                          left.ljust(20) + (" - %10d in %10.6fs" % [@iterations, runtime])
         
     | 
    
        data/lib/benchmark/ips/share.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'net/http'
         
     | 
| 
       2 
4 
     | 
    
         
             
            require 'net/https'
         
     | 
| 
       3 
5 
     | 
    
         
             
            require 'json'
         
     | 
| 
         @@ -5,7 +7,7 @@ require 'json' 
     | 
|
| 
       5 
7 
     | 
    
         
             
            module Benchmark
         
     | 
| 
       6 
8 
     | 
    
         
             
              module IPS
         
     | 
| 
       7 
9 
     | 
    
         
             
                class Share
         
     | 
| 
       8 
     | 
    
         
            -
                  DEFAULT_URL = "https:// 
     | 
| 
      
 10 
     | 
    
         
            +
                  DEFAULT_URL = "https://ips.fastruby.io"
         
     | 
| 
       9 
11 
     | 
    
         
             
                  def initialize(report, job)
         
     | 
| 
       10 
12 
     | 
    
         
             
                    @report = report
         
     | 
| 
       11 
13 
     | 
    
         
             
                    @job = job
         
     | 
| 
         @@ -3,27 +3,30 @@ module Benchmark 
     | 
|
| 
       3 
3 
     | 
    
         
             
                module Stats
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                  class Bootstrap
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                    attr_reader :data
         
     | 
| 
      
 6 
     | 
    
         
            +
                    include StatsMetric
         
     | 
| 
      
 7 
     | 
    
         
            +
                    attr_reader :data, :error, :samples
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                    def initialize(samples, confidence)
         
     | 
| 
       10 
10 
     | 
    
         
             
                      dependencies
         
     | 
| 
       11 
11 
     | 
    
         
             
                      @iterations = 10_000
         
     | 
| 
       12 
12 
     | 
    
         
             
                      @confidence = (confidence / 100.0).to_s
         
     | 
| 
      
 13 
     | 
    
         
            +
                      @samples = samples
         
     | 
| 
       13 
14 
     | 
    
         
             
                      @data = Kalibera::Data.new({[0] => samples}, [1, samples.size])
         
     | 
| 
       14 
15 
     | 
    
         
             
                      interval = @data.bootstrap_confidence_interval(@iterations, @confidence)
         
     | 
| 
       15 
16 
     | 
    
         
             
                      @median = interval.median
         
     | 
| 
       16 
17 
     | 
    
         
             
                      @error = interval.error
         
     | 
| 
       17 
18 
     | 
    
         
             
                    end
         
     | 
| 
       18 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
                    # Average stat value
         
     | 
| 
      
 21 
     | 
    
         
            +
                    # @return [Float] central_tendency
         
     | 
| 
       19 
22 
     | 
    
         
             
                    def central_tendency
         
     | 
| 
       20 
23 
     | 
    
         
             
                      @median
         
     | 
| 
       21 
24 
     | 
    
         
             
                    end
         
     | 
| 
       22 
25 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                     
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                    # Determines how much slower this stat is than the baseline stat
         
     | 
| 
      
 27 
     | 
    
         
            +
                    # if this average is lower than the faster baseline, higher average is better (e.g. ips) (calculate accordingly)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # @param baseline [SD|Bootstrap] faster baseline
         
     | 
| 
      
 29 
     | 
    
         
            +
                    # @returns [Array<Float, nil>] the slowdown and the error (not calculated for standard deviation)
         
     | 
| 
       27 
30 
     | 
    
         
             
                    def slowdown(baseline)
         
     | 
| 
       28 
31 
     | 
    
         
             
                      low, slowdown, high = baseline.data.bootstrap_quotient(@data, @iterations, @confidence)
         
     | 
| 
       29 
32 
     | 
    
         
             
                      error = Timing.mean([slowdown - low, high - slowdown])
         
     | 
| 
         @@ -1,33 +1,41 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Benchmark
         
     | 
| 
       2 
2 
     | 
    
         
             
              module IPS
         
     | 
| 
       3 
3 
     | 
    
         
             
                module Stats
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       5 
5 
     | 
    
         
             
                  class SD
         
     | 
| 
       6 
     | 
    
         
            -
                    
         
     | 
| 
      
 6 
     | 
    
         
            +
                    include StatsMetric
         
     | 
| 
      
 7 
     | 
    
         
            +
                    attr_reader :error, :samples
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       7 
9 
     | 
    
         
             
                    def initialize(samples)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @samples = samples
         
     | 
| 
       8 
11 
     | 
    
         
             
                      @mean = Timing.mean(samples)
         
     | 
| 
       9 
12 
     | 
    
         
             
                      @error = Timing.stddev(samples, @mean).round
         
     | 
| 
       10 
13 
     | 
    
         
             
                    end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    # Average stat value
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # @return [Float] central_tendency
         
     | 
| 
       12 
17 
     | 
    
         
             
                    def central_tendency
         
     | 
| 
       13 
18 
     | 
    
         
             
                      @mean
         
     | 
| 
       14 
19 
     | 
    
         
             
                    end
         
     | 
| 
       15 
     | 
    
         
            -
                    
         
     | 
| 
       16 
     | 
    
         
            -
                    def error
         
     | 
| 
       17 
     | 
    
         
            -
                      @error
         
     | 
| 
       18 
     | 
    
         
            -
                    end
         
     | 
| 
       19 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                    # Determines how much slower this stat is than the baseline stat
         
     | 
| 
      
 22 
     | 
    
         
            +
                    # if this average is lower than the faster baseline, higher average is better (e.g. ips) (calculate accordingly)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    # @param baseline [SD|Bootstrap] faster baseline
         
     | 
| 
      
 24 
     | 
    
         
            +
                    # @returns [Array<Float, nil>] the slowdown and the error (not calculated for standard deviation)
         
     | 
| 
       20 
25 
     | 
    
         
             
                    def slowdown(baseline)
         
     | 
| 
       21 
     | 
    
         
            -
                       
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                      if baseline.central_tendency > central_tendency
         
     | 
| 
      
 27 
     | 
    
         
            +
                        [baseline.central_tendency.to_f / central_tendency, 0]
         
     | 
| 
      
 28 
     | 
    
         
            +
                      else
         
     | 
| 
      
 29 
     | 
    
         
            +
                        [central_tendency.to_f / baseline.central_tendency, 0]
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
       23 
31 
     | 
    
         
             
                    end
         
     | 
| 
       24 
32 
     | 
    
         | 
| 
       25 
33 
     | 
    
         
             
                    def footer
         
     | 
| 
       26 
34 
     | 
    
         
             
                      nil
         
     | 
| 
       27 
35 
     | 
    
         
             
                    end
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       29 
37 
     | 
    
         
             
                  end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       31 
39 
     | 
    
         
             
                end
         
     | 
| 
       32 
40 
     | 
    
         
             
              end
         
     | 
| 
       33 
41 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Benchmark
         
     | 
| 
      
 2 
     | 
    
         
            +
              module IPS
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Stats
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module StatsMetric
         
     | 
| 
      
 5 
     | 
    
         
            +
                    # Return entry's standard deviation of iteration per second in percentage.
         
     | 
| 
      
 6 
     | 
    
         
            +
                    # @return [Float] +@ips_sd+ in percentage.
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def error_percentage
         
     | 
| 
      
 8 
     | 
    
         
            +
                      100.0 * (error.to_f / central_tendency)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def overlaps?(baseline)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      baseline_low = baseline.central_tendency - baseline.error
         
     | 
| 
      
 13 
     | 
    
         
            +
                      baseline_high = baseline.central_tendency + baseline.error
         
     | 
| 
      
 14 
     | 
    
         
            +
                      my_high = central_tendency + error
         
     | 
| 
      
 15 
     | 
    
         
            +
                      my_low  = central_tendency - error
         
     | 
| 
      
 16 
     | 
    
         
            +
                      my_high > baseline_low && my_low < baseline_high
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
    
        data/test/test_benchmark_ips.rb
    CHANGED
    
    | 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "minitest/autorun"
         
     | 
| 
       2 
2 
     | 
    
         
             
            require "benchmark/ips"
         
     | 
| 
       3 
3 
     | 
    
         
             
            require "stringio"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "tmpdir"
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            class TestBenchmarkIPS < Minitest::Test
         
     | 
| 
       6 
7 
     | 
    
         
             
              def setup
         
     | 
| 
         @@ -20,6 +21,19 @@ class TestBenchmarkIPS < Minitest::Test 
     | 
|
| 
       20 
21 
     | 
    
         
             
                assert $stdout.string.size > 0
         
     | 
| 
       21 
22 
     | 
    
         
             
              end
         
     | 
| 
       22 
23 
     | 
    
         | 
| 
      
 24 
     | 
    
         
            +
              def test_warmup0
         
     | 
| 
      
 25 
     | 
    
         
            +
                $stdout = @old_stdout
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                out, err = capture_io do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  Benchmark.ips(:time => 1, :warmup => 0, :quiet => false) do |x|
         
     | 
| 
      
 29 
     | 
    
         
            +
                    x.report("sleep 0.25") { sleep(0.25) }
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                refute_match(/Warming up -+/, out)
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert_empty err
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       23 
37 
     | 
    
         
             
              def test_output
         
     | 
| 
       24 
38 
     | 
    
         
             
                Benchmark.ips(1) do |x|
         
     | 
| 
       25 
39 
     | 
    
         
             
                  x.report("operation") { 100 * 100 }
         
     | 
| 
         @@ -40,6 +54,13 @@ class TestBenchmarkIPS < Minitest::Test 
     | 
|
| 
       40 
54 
     | 
    
         
             
                end
         
     | 
| 
       41 
55 
     | 
    
         | 
| 
       42 
56 
     | 
    
         
             
                assert $stdout.string.size.zero?
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                Benchmark.ips do |x|
         
     | 
| 
      
 59 
     | 
    
         
            +
                  x.quiet = true
         
     | 
| 
      
 60 
     | 
    
         
            +
                  x.report("operation") { 100 * 100 }
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                assert $stdout.string.size.zero?
         
     | 
| 
       43 
64 
     | 
    
         
             
              end
         
     | 
| 
       44 
65 
     | 
    
         | 
| 
       45 
66 
     | 
    
         
             
              def test_ips
         
     | 
| 
         @@ -103,6 +124,21 @@ class TestBenchmarkIPS < Minitest::Test 
     | 
|
| 
       103 
124 
     | 
    
         
             
                assert_equal [:warming, :warmup_stats, :running, :add_report], suite.calls
         
     | 
| 
       104 
125 
     | 
    
         
             
              end
         
     | 
| 
       105 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
              def test_ips_config_suite_by_accsr
         
     | 
| 
      
 128 
     | 
    
         
            +
                suite = Struct.new(:calls) do
         
     | 
| 
      
 129 
     | 
    
         
            +
                  def method_missing(method, *args)
         
     | 
| 
      
 130 
     | 
    
         
            +
                    calls << method
         
     | 
| 
      
 131 
     | 
    
         
            +
                  end
         
     | 
| 
      
 132 
     | 
    
         
            +
                end.new([])
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                Benchmark.ips(0.1, 0.1) do |x|
         
     | 
| 
      
 135 
     | 
    
         
            +
                  x.suite = suite
         
     | 
| 
      
 136 
     | 
    
         
            +
                  x.report("job") {}
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                assert_equal [:warming, :warmup_stats, :running, :add_report], suite.calls
         
     | 
| 
      
 140 
     | 
    
         
            +
              end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
       106 
142 
     | 
    
         
             
              def test_ips_defaults
         
     | 
| 
       107 
143 
     | 
    
         
             
                report = Benchmark.ips do |x|
         
     | 
| 
       108 
144 
     | 
    
         
             
                  x.report("sleep 0.25") { sleep(0.25) }
         
     | 
| 
         @@ -140,6 +176,17 @@ class TestBenchmarkIPS < Minitest::Test 
     | 
|
| 
       140 
176 
     | 
    
         
             
                assert all_data[0][:stddev]
         
     | 
| 
       141 
177 
     | 
    
         
             
              end
         
     | 
| 
       142 
178 
     | 
    
         | 
| 
      
 179 
     | 
    
         
            +
              def test_ips_empty
         
     | 
| 
      
 180 
     | 
    
         
            +
                report = Benchmark.ips do |_x|
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                all_data = report.data
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                assert all_data
         
     | 
| 
      
 187 
     | 
    
         
            +
                assert_equal [], all_data
         
     | 
| 
      
 188 
     | 
    
         
            +
              end
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
       143 
190 
     | 
    
         
             
              def test_json_output
         
     | 
| 
       144 
191 
     | 
    
         
             
                json_file = Tempfile.new("data.json")
         
     | 
| 
       145 
192 
     | 
    
         | 
| 
         @@ -158,4 +205,17 @@ class TestBenchmarkIPS < Minitest::Test 
     | 
|
| 
       158 
205 
     | 
    
         
             
                assert data[0]["ips"]
         
     | 
| 
       159 
206 
     | 
    
         
             
                assert data[0]["stddev"]
         
     | 
| 
       160 
207 
     | 
    
         
             
              end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
              def test_hold!
         
     | 
| 
      
 210 
     | 
    
         
            +
                temp_file_name = Dir::Tmpname.create(["benchmark-ips", ".tmp"]) { }
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                Benchmark.ips(:time => 0.001, :warmup => 0.001) do |x|
         
     | 
| 
      
 213 
     | 
    
         
            +
                  x.report("operation") { 100 * 100 }
         
     | 
| 
      
 214 
     | 
    
         
            +
                  x.report("operation2") { 100 * 100 }
         
     | 
| 
      
 215 
     | 
    
         
            +
                  x.hold! temp_file_name
         
     | 
| 
      
 216 
     | 
    
         
            +
                end
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                assert File.exist?(temp_file_name)
         
     | 
| 
      
 219 
     | 
    
         
            +
                File.unlink(temp_file_name)
         
     | 
| 
      
 220 
     | 
    
         
            +
              end
         
     | 
| 
       161 
221 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,57 +1,63 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: benchmark-ips
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.9.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Evan Phoenix
         
     | 
| 
       8 
     | 
    
         
            -
            autorequire: 
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-05-21 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
     | 
    
         
            -
              name: minitest
         
     | 
| 
       15 
14 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       16 
15 
     | 
    
         
             
                requirements:
         
     | 
| 
       17 
16 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       18 
17 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       19 
     | 
    
         
            -
                    version: '5. 
     | 
| 
       20 
     | 
    
         
            -
               
     | 
| 
      
 18 
     | 
    
         
            +
                    version: '5.14'
         
     | 
| 
      
 19 
     | 
    
         
            +
              name: minitest
         
     | 
| 
       21 
20 
     | 
    
         
             
              prerelease: false
         
     | 
| 
      
 21 
     | 
    
         
            +
              type: :development
         
     | 
| 
       22 
22 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       23 
23 
     | 
    
         
             
                requirements:
         
     | 
| 
       24 
24 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       25 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       26 
     | 
    
         
            -
                    version: '5. 
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '5.14'
         
     | 
| 
       27 
27 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       28 
     | 
    
         
            -
              name: rdoc
         
     | 
| 
       29 
28 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       30 
29 
     | 
    
         
             
                requirements:
         
     | 
| 
       31 
     | 
    
         
            -
                - - " 
     | 
| 
      
 30 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       32 
31 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       33 
32 
     | 
    
         
             
                    version: '4.0'
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 33 
     | 
    
         
            +
                - - "<"
         
     | 
| 
      
 34 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 35 
     | 
    
         
            +
                    version: '7'
         
     | 
| 
      
 36 
     | 
    
         
            +
              name: rdoc
         
     | 
| 
       35 
37 
     | 
    
         
             
              prerelease: false
         
     | 
| 
      
 38 
     | 
    
         
            +
              type: :development
         
     | 
| 
       36 
39 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       37 
40 
     | 
    
         
             
                requirements:
         
     | 
| 
       38 
     | 
    
         
            -
                - - " 
     | 
| 
      
 41 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       39 
42 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       40 
43 
     | 
    
         
             
                    version: '4.0'
         
     | 
| 
      
 44 
     | 
    
         
            +
                - - "<"
         
     | 
| 
      
 45 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 46 
     | 
    
         
            +
                    version: '7'
         
     | 
| 
       41 
47 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       42 
     | 
    
         
            -
              name: hoe
         
     | 
| 
       43 
48 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       44 
49 
     | 
    
         
             
                requirements:
         
     | 
| 
       45 
50 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       46 
51 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       47 
     | 
    
         
            -
                    version: '3. 
     | 
| 
       48 
     | 
    
         
            -
               
     | 
| 
      
 52 
     | 
    
         
            +
                    version: '3.22'
         
     | 
| 
      
 53 
     | 
    
         
            +
              name: hoe
         
     | 
| 
       49 
54 
     | 
    
         
             
              prerelease: false
         
     | 
| 
      
 55 
     | 
    
         
            +
              type: :development
         
     | 
| 
       50 
56 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       51 
57 
     | 
    
         
             
                requirements:
         
     | 
| 
       52 
58 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       53 
59 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       54 
     | 
    
         
            -
                    version: '3. 
     | 
| 
      
 60 
     | 
    
         
            +
                    version: '3.22'
         
     | 
| 
       55 
61 
     | 
    
         
             
            description: An iterations per second enhancement to Benchmark.
         
     | 
| 
       56 
62 
     | 
    
         
             
            email:
         
     | 
| 
       57 
63 
     | 
    
         
             
            - evan@phx.io
         
     | 
| 
         @@ -63,7 +69,6 @@ extra_rdoc_files: 
     | 
|
| 
       63 
69 
     | 
    
         
             
            - README.md
         
     | 
| 
       64 
70 
     | 
    
         
             
            files:
         
     | 
| 
       65 
71 
     | 
    
         
             
            - ".autotest"
         
     | 
| 
       66 
     | 
    
         
            -
            - Gemfile.lock
         
     | 
| 
       67 
72 
     | 
    
         
             
            - History.txt
         
     | 
| 
       68 
73 
     | 
    
         
             
            - Manifest.txt
         
     | 
| 
       69 
74 
     | 
    
         
             
            - README.md
         
     | 
| 
         @@ -77,13 +82,15 @@ files: 
     | 
|
| 
       77 
82 
     | 
    
         
             
            - lib/benchmark/ips/share.rb
         
     | 
| 
       78 
83 
     | 
    
         
             
            - lib/benchmark/ips/stats/bootstrap.rb
         
     | 
| 
       79 
84 
     | 
    
         
             
            - lib/benchmark/ips/stats/sd.rb
         
     | 
| 
      
 85 
     | 
    
         
            +
            - lib/benchmark/ips/stats/stats_metric.rb
         
     | 
| 
       80 
86 
     | 
    
         
             
            - lib/benchmark/timing.rb
         
     | 
| 
       81 
87 
     | 
    
         
             
            - test/test_benchmark_ips.rb
         
     | 
| 
       82 
88 
     | 
    
         
             
            homepage: https://github.com/evanphx/benchmark-ips
         
     | 
| 
       83 
89 
     | 
    
         
             
            licenses:
         
     | 
| 
       84 
90 
     | 
    
         
             
            - MIT
         
     | 
| 
       85 
     | 
    
         
            -
            metadata: 
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
      
 91 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 92 
     | 
    
         
            +
              homepage_uri: https://github.com/evanphx/benchmark-ips
         
     | 
| 
      
 93 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
       87 
94 
     | 
    
         
             
            rdoc_options:
         
     | 
| 
       88 
95 
     | 
    
         
             
            - "--main"
         
     | 
| 
       89 
96 
     | 
    
         
             
            - README.md
         
     | 
| 
         @@ -100,9 +107,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       100 
107 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       101 
108 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       102 
109 
     | 
    
         
             
            requirements: []
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
            signing_key: 
         
     | 
| 
      
 110 
     | 
    
         
            +
            rubygems_version: 3.1.6
         
     | 
| 
      
 111 
     | 
    
         
            +
            signing_key:
         
     | 
| 
       106 
112 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       107 
113 
     | 
    
         
             
            summary: An iterations per second enhancement to Benchmark.
         
     | 
| 
       108 
114 
     | 
    
         
             
            test_files: []
         
     | 
    
        data/Gemfile.lock
    DELETED