benchmark-ips 2.3.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ac378dafa55fa25f223374c352d9fce265a73a1d
4
- data.tar.gz: edcbad0a3ed40b69793e18b52b40b4d2d73b72fd
2
+ SHA256:
3
+ metadata.gz: 0516f3e1e35f43a8fe32a6f32357aa124478ba54228ffe57d928cfc1231851bc
4
+ data.tar.gz: d62da6a6c1d2696b7667bd125ffe6bb2c33b3d61da5c393e729d7ca8a3d70ee7
5
5
  SHA512:
6
- metadata.gz: 427e884910dc92a0e50ceb825ff36770b70c0dcee9088f56d3e090867986f6c8d12d176c7a671d7b964f15c12c2ae6edd4c87b532c6c68bdd351c0508c03fd90
7
- data.tar.gz: 3db5f1f4445eb0b2c4985633a197abf58be95f9a2bb01282bda329c2880916e1c25c5cd0ec94b2a17adbdc667e3e8829dd46fa428ef13dc41cf3327136564d89
6
+ metadata.gz: b644d293980f1ac9e3158abbe4f2c9d44d23185878edb9cb3861f3ca4f6837d557f89f8eb19bfcc42a45f53f3d112f2fe3ab22fc85a9633ede7e678b5fb90336
7
+ data.tar.gz: afe9972cdecdb2f42d4946afbac3d02cb3ead3a3d47a804960026ea77487cf885f6ddd7368edb13c522ee11e251599bf953d3d9a8172411c10e7259f7e9352b2
data/History.md ADDED
@@ -0,0 +1,223 @@
1
+ ### 2.10.0 / 2022-02-17
2
+
3
+ * Feature
4
+ * Adds :order option to compare, with new `:baseline` order which compares all
5
+ variations against the first option benchmarked.
6
+
7
+ ### 2.9.3 / 2022-01-25
8
+
9
+ * Bug fix
10
+ * All warmups and benchmarks must run at least once
11
+
12
+ ### 2.9.2 / 2021-10-10
13
+
14
+ * Bug fix
15
+ * Fix a problem with certain configs of quiet mode
16
+
17
+ ### 2.9.1 / 2021-05-24
18
+
19
+ * Bug fix
20
+ * Include all files in gem
21
+
22
+ ### 2.9.0 / 2021-05-21
23
+
24
+ * Features
25
+ * Suite can now be set via an accessor
26
+ * Default SHARE_URL is now `ips.fastruby.io`, operated by Ombu Labs.
27
+
28
+ ### 2.8.4 / 2020-12-03
29
+
30
+ * Bug fix
31
+ * Fixed hold! when results file does not exist.
32
+
33
+ ### 2.8.3 / 2020-08-28
34
+
35
+ * Bug fix
36
+ * Fixed inaccuracy caused by integer overflows.
37
+
38
+ ### 2.8.2 / 2020-05-04
39
+
40
+ * Bug fix
41
+ * Fixed problems with Manifest.txt.
42
+ * Empty interim results files are ignored.
43
+
44
+ ### 2.8.0 / 2020-05-01
45
+
46
+ * Feature
47
+ * Allow running with empty ips block.
48
+ * Added save! method for saving interim results.
49
+ * Run more than just 1 cycle during warmup to reduce overhead.
50
+ * Optimized Job::Entry hot-path for fairer results on JRuby/TruffleRuby.
51
+
52
+ * Bug fix
53
+ * Removed the warmup section if set to 0.
54
+ * Added some RDoc docs.
55
+ * Added some examples in examples/
56
+
57
+ ### 2.7.2 / 2016-08-18
58
+
59
+ * 1 bug fix:
60
+ * Restore old accessors. Fixes #76
61
+
62
+ ### 2.7.1 / 2016-08-08
63
+
64
+ Add missing files
65
+
66
+ ### 2.7.0 / 2016-08-05
67
+
68
+ * 1 minor features:
69
+ * Add support for confidence intervals
70
+
71
+ * 1 bug fixes:
72
+ * Cleanup a few coding patterns
73
+
74
+ * 2 doc fixes:
75
+ * Add infos about benchark.fyi to Readme
76
+ * Remove ancient releases
77
+
78
+ * 3 merged PRs:
79
+ * Merge pull request #65 from kbrock/fixup_inject
80
+ * Merge pull request #67 from benoittgt/master
81
+ * Merge pull request #69 from chrisseaton/kalibera-confidence-intervals
82
+
83
+ ### MISSING 2.6.0 and 2.6.1
84
+
85
+ ### 2.5.0 / 2016-02-14
86
+
87
+ * 1 minor feature:
88
+ * Add iterations option.
89
+
90
+ * 1 bug fixes:
91
+ * Don't tell people something is slower if it's within the error.
92
+
93
+ * 2 merged PRs:
94
+ * Merge pull request #58 from chrisseaton/iterations
95
+ * Merge pull request #60 from chrisseaton/significance
96
+
97
+ ### 2.4.1 / 2016-02-12
98
+
99
+ * 1 bug fix:
100
+ * Add missing files to gem
101
+
102
+ ### 2.4.0 / 2016-02-12
103
+
104
+ * 1 minor features
105
+ * Add support for hold! and independent invocations.
106
+
107
+ * 6 bug fixes
108
+ * Separate messages for warming up and calculating.
109
+ * Tighten timing loop.
110
+ * Pass simple types into Job#create_report
111
+ * More concise sorting
112
+ * Fix runtime comparison
113
+ * Use runtime if ips is not available
114
+
115
+ * 5 doc fixes
116
+ * Fix typo unsed --> used
117
+ * Better document Report::Entry
118
+ * Fix some typos in docs
119
+ * Don't calculate mean 2 times
120
+ * Add more tolerance to tests
121
+
122
+ * 13 merged PRs
123
+ * Merge pull request #44 from kbrock/job_extract
124
+ * Merge pull request #45 from kbrock/runtime_only
125
+ * Merge pull request #47 from kbrock/use_avg
126
+ * Merge pull request #46 from kbrock/report_stdout
127
+ * Merge pull request #48 from bquorning/fix-label-for-runtime-comparison
128
+ * Merge pull request #50 from tjschuck/fix_typo
129
+ * Merge pull request #51 from bquorning/all-reports-respond-to-ips
130
+ * Merge pull request #52 from kbrock/document_reports
131
+ * Merge pull request #53 from kbrock/interface_create_report
132
+ * Merge pull request #54 from PragTob/patch-2
133
+ * Merge pull request #55 from chrisseaton/messages
134
+ * Merge pull request #56 from chrisseaton/independence
135
+ * Merge pull request #57 from chrisseaton/tighten-loop
136
+
137
+ ### 2.3.0 / 2015-07-20
138
+
139
+ * 2 minor features:
140
+ * Support keyword arguments
141
+ * Allow any datatype for labels (use #to_s conversion)
142
+
143
+ * 1 doc/test changes:
144
+ * Newer Travis for 1.8.7, ree, and 2.2.2
145
+
146
+ * 3 PRs merged:
147
+ * Merge pull request #41 from kbrock/kwargs-support
148
+ * Merge pull request #42 from kbrock/newer_travis
149
+ * Merge pull request #43 from kbrock/non_to_s_labels
150
+
151
+ ### 2.2.0 / 2015-05-09
152
+
153
+ * 1 minor features:
154
+ * Fix quiet mode
155
+ * Allow passing a custom suite via config
156
+ * Silent a job if a suite was passed and is quiet
157
+ * Export report to json file.
158
+ * Accept symbol as report's argument.
159
+
160
+ * 2 doc fixes:
161
+ * Squish duplicate `to` in README
162
+ * Update copyright to 2015. [ci skip]
163
+
164
+ * 9 PRs merged:
165
+ * Merge pull request #37 from splattael/patch-1
166
+ * Merge pull request #36 from kirs/quiet-mode
167
+ * Merge pull request #35 from JuanitoFatas/doc/suite
168
+ * Merge pull request #34 from splattael/config-suite
169
+ * Merge pull request #33 from splattael/suite-quiet
170
+ * Merge pull request #32 from O-I/remove-gemfile-lock
171
+ * Merge pull request #31 from JuanitoFatas/doc/bump-copyright-year
172
+ * Merge pull request #29 from JuanitoFatas/feature/json-export
173
+ * Merge pull request #26 from JuanitoFatas/feature/takes-symbol-as-report-parameter
174
+
175
+ ### 2.1.1 / 2015-01-12
176
+
177
+ * 1 minor fix:
178
+ * Don't send label through printf so that % work directly
179
+
180
+ * 1 documenation changes:
181
+ * Use HEREDOC and wrap at 80 chars for example result description
182
+
183
+ * 1 usage fix:
184
+ * Add gemspec for use via bundler git
185
+
186
+ * 1 PR merged:
187
+ * Merge pull request #24 from zzak/simple-format-result-description
188
+
189
+ ### 2.1.0 / 2014-11-10
190
+
191
+ * Documentation changes:
192
+ * Many documentation fixes by Juanito Fatas!
193
+ * Minor readme fix by Will Leinweber
194
+
195
+ * 2 minor features:
196
+ * Displaying the total runtime for a job is suppressed unless interesting
197
+ * Formatting of large values improved (human vs raw mode)
198
+ * Contributed by Charles Oliver Nutter
199
+
200
+ ### 2.0.0 / 2014-06-18
201
+
202
+ * The 'Davy Stevenson' release!
203
+ * Codename: Springtime Hummingbird Dance
204
+
205
+ * Big API refactoring so the internal bits are easier to use
206
+ * Bump to 2.0 because return types changed to make the API better
207
+
208
+ * Contributors added:
209
+ * Davy Stevenson
210
+ * Juanito Fatas
211
+ * Benoit Daloze
212
+ * Matias
213
+ * Tony Arcieri
214
+ * Vipul A M
215
+ * Zachary Scott
216
+ * schneems (Richard Schneeman)
217
+
218
+ ### 1.0.0 / 2012-03-23
219
+
220
+ * 1 major enhancement
221
+
222
+ * Birthday!
223
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Evan Phoenix
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,16 +1,17 @@
1
+ # benchmark-ips
2
+
3
+ * rdoc :: http://rubydoc.info/gems/benchmark-ips
4
+ * home :: https://github.com/evanphx/benchmark-ips
5
+
1
6
  [![Gem Version](https://badge.fury.io/rb/benchmark-ips.svg)](http://badge.fury.io/rb/benchmark-ips)
2
7
  [![Build Status](https://secure.travis-ci.org/evanphx/benchmark-ips.svg)](http://travis-ci.org/evanphx/benchmark-ips)
3
8
  [![Inline docs](http://inch-ci.org/github/evanphx/benchmark-ips.svg)](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
- A iterations per second enhancement to Benchmark.
14
+ An iterations per second enhancement to Benchmark.
14
15
 
15
16
  ## FEATURES/PROBLEMS:
16
17
 
@@ -136,6 +137,106 @@ Benchmark.ips do |x|
136
137
  end
137
138
  ```
138
139
 
140
+ ### Independent benchmarking
141
+
142
+ If you are comparing multiple implementations of a piece of code you may want
143
+ to benchmark them in separate invocations of Ruby so that the measurements
144
+ are independent of each other. You can do this with the `hold!` command.
145
+
146
+ ```ruby
147
+ Benchmark.ips do |x|
148
+
149
+ # Hold results between multiple invocations of Ruby
150
+ x.hold! 'filename'
151
+
152
+ end
153
+ ```
154
+
155
+ This will run only one benchmarks each time you run the command, storing
156
+ results in the specified file. The file is deleted when all results have been
157
+ gathered and the report is shown.
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
+
164
+ ### Multiple iterations
165
+
166
+ In some cases you may want to run multiple iterations of the warmup and
167
+ calculation stages and take only the last result for comparison. This is useful
168
+ if you are benchmarking with an implementation of Ruby that optimizes using
169
+ tracing or on-stack-replacement, because to those implementations the
170
+ calculation phase may appear as new, unoptimized code.
171
+
172
+ You can do this with the `iterations` option, which by default is `1`. The
173
+ total time spent will then be `iterations * warmup + iterations * time` seconds.
174
+
175
+ ```ruby
176
+ Benchmark.ips do |x|
177
+
178
+ x.config(:iterations => 3)
179
+
180
+ # or
181
+
182
+ x.iterations = 3
183
+
184
+ end
185
+ ```
186
+
187
+ ### Online sharing
188
+
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
193
+ will display the link to share the benchmark's result.
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
+
198
+ ### Advanced Statistics
199
+
200
+ By default, the margin of error shown is plus-minus one standard deviation. If
201
+ a more advanced statistical test is wanted, a bootstrap confidence interval
202
+ can be calculated instead. A bootstrap confidence interval has the advantages of
203
+ arguably being more mathematically sound for this application than a standard
204
+ deviation, it additionally produces an error for relative slowdowns, which the
205
+ standard deviation does not, and it is arguably more intuitive and actionable.
206
+
207
+ When a bootstrap confidence interval is used, a median of the interval is used
208
+ rather than the mean of the samples, which is what you get with the default
209
+ standard deviation.
210
+
211
+ The bootstrap confidence interval used is the one described by Tomas Kalibera.
212
+ Note that for this technique to be valid your benchmark should have reached a
213
+ non-periodic steady state with statistically independent samples (it should
214
+ have warmed up) by the time measurements start.
215
+
216
+ Using a bootstrap confidence internal requires that the 'kalibera' gem is
217
+ installed separately. This gem is not a formal dependency, as by default it is
218
+ not needed.
219
+
220
+ ```
221
+ gem install kalibera
222
+ ```
223
+
224
+ ```ruby
225
+ Benchmark.ips do |x|
226
+
227
+ # The default is :stats => :sd, which doesn't have a configurable confidence
228
+ x.config(:stats => :bootstrap, :confidence => 95)
229
+
230
+ # or
231
+
232
+ x.stats = :bootstrap
233
+ x.confidence = 95
234
+
235
+ # confidence is 95% by default, so it can be omitted
236
+
237
+ end
238
+ ```
239
+
139
240
  ## REQUIREMENTS:
140
241
 
141
242
  * None!
@@ -153,27 +254,3 @@ After checking out the source, run:
153
254
  This task will install any missing dependencies, run the tests/specs,
154
255
  and generate the RDoc.
155
256
 
156
- ## LICENSE:
157
-
158
- (The MIT License)
159
-
160
- Copyright (c) 2015 Evan Phoenix
161
-
162
- Permission is hereby granted, free of charge, to any person obtaining
163
- a copy of this software and associated documentation files (the
164
- 'Software'), to deal in the Software without restriction, including
165
- without limitation the rights to use, copy, modify, merge, publish,
166
- distribute, sublicense, and/or sell copies of the Software, and to
167
- permit persons to whom the Software is furnished to do so, subject to
168
- the following conditions:
169
-
170
- The above copyright notice and this permission notice shall be
171
- included in all copies or substantial portions of the Software.
172
-
173
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
174
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
175
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
176
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
177
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
178
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
179
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'benchmark/ips'
4
+
5
+ Benchmark.ips do |x|
6
+
7
+ # Use bootstrap confidence intervals
8
+ x.stats = :bootstrap
9
+
10
+ # Set confidence to 95%
11
+ x.confidence = 95
12
+
13
+ # Run multiple iterations for better warmup
14
+ x.iterations = 3
15
+
16
+ x.report("mul") { 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 }
17
+ x.report("pow") { 2 ** 8 }
18
+
19
+ x.compare!
20
+ end
data/examples/hold.rb ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+ # example to explain hold! usage https://github.com/evanphx/benchmark-ips/issues/85
3
+ # The hold! feature expects to be run twice, generally with different Rubys.
4
+ # hold! can also be used to compare modules changes which impact the run time
5
+ # RUN_1: ruby examples/hold.rb
6
+ # Warming up --------------------------------------
7
+ # without 172.168k i/100ms
8
+ # Calculating -------------------------------------
9
+ # without 2.656M (± 3.3%) i/s - 13.429M in 5.062098s
10
+ #
11
+ # RUN_2: WITH_MODULE=true ruby examples/hold.rb
12
+ # Warming up --------------------------------------
13
+ # with 92.087k i/100ms
14
+ # Calculating -------------------------------------
15
+ # with 1.158M (± 1.4%) i/s - 5.801M in 5.010084s
16
+ #
17
+ # Comparison:
18
+ # without: 2464721.3 i/s
19
+ # with: 1158179.6 i/s - 2.13x slower
20
+ require 'benchmark/ips'
21
+
22
+ Benchmark.ips do |x|
23
+ x.report('without') do
24
+ 'Bruce'.inspect
25
+ end
26
+
27
+ if ENV['WITH_MODULE'] == 'true'
28
+ class String
29
+ def inspect
30
+ result = %w[Bruce Wayne is Batman]
31
+ result.join(' ')
32
+ end
33
+ end
34
+ end
35
+
36
+ x.report('with') do
37
+ 'Bruce'.inspect
38
+ end
39
+ x.hold! 'temp_results'
40
+ x.compare!
41
+ end
data/examples/save.rb ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # example to explain save!
4
+ # The save! feature expects to be run twice, generally with different Rubys.
5
+ # save! can also be used to compare modules changes which impact the run time
6
+ #
7
+ # If you're comparing ruby versions, Just use the version in the label
8
+ #
9
+ # x.report("ruby #{RUBY_VERSION}") { 'Bruce'.inspect }
10
+ #
11
+ # Or use a hash
12
+ #
13
+ # x.report("version" => RUBY_VERSION, "method" => 'bruce') { 'Bruce'.inspect }
14
+ #
15
+ # RUN_1: SAVE_FILE='run1.out' ruby examples/hold.rb
16
+ # Warming up --------------------------------------
17
+ # without 172.168k i/100ms
18
+ # Calculating -------------------------------------
19
+ # without 2.656M (± 3.3%) i/s - 13.429M in 5.062098s
20
+ #
21
+ # RUN_2: SAVE_FILE='run1.out' WITH_MODULE=true ruby examples/hold.rb
22
+ # Warming up --------------------------------------
23
+ # with 92.087k i/100ms
24
+ # Calculating -------------------------------------
25
+ # with 1.158M (± 1.4%) i/s - 5.801M in 5.010084s
26
+ #
27
+ # Comparison:
28
+ # without: 2464721.3 i/s
29
+ # with: 1158179.6 i/s - 2.13x slower
30
+ # CLEANUP: rm run1.out
31
+
32
+ require 'benchmark/ips'
33
+
34
+ Benchmark.ips do |x|
35
+ x.report(ENV['WITH_MODULE'] == 'true' ? 'with' : 'without') do
36
+ 'Bruce'.inspect
37
+ end
38
+
39
+ if ENV['WITH_MODULE'] == 'true'
40
+ class String
41
+ def inspect
42
+ result = %w[Bruce Wayne is Batman]
43
+ result.join(' ')
44
+ end
45
+ end
46
+ end
47
+
48
+ x.save! ENV['SAVE_FILE'] if ENV['SAVE_FILE']
49
+ x.compare!
50
+ end
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'benchmark/ips'
4
+
5
+ Benchmark.ips do |x|
6
+
7
+ # Configure the number of seconds used during
8
+ # the warmup phase and calculation phase
9
+ x.config(:time => 5, :warmup => 2)
10
+
11
+ # These parameters can also be configured this way
12
+ x.time = 5
13
+ x.warmup = 2
14
+
15
+ # Typical mode, runs the block as many times as it can
16
+ x.report("addition") { 1 + 2 }
17
+
18
+ # To reduce overhead, the number of iterations is passed in
19
+ # and the block must run the code the specific number of times.
20
+ # Used for when the workload is very small and any overhead
21
+ # introduces incorrectable errors.
22
+ x.report(:addition2) do |times|
23
+ i = 0
24
+ while i < times
25
+ 1 + 2
26
+ i += 1
27
+ end
28
+ end
29
+
30
+ # To reduce overhead even more, grafts the code given into
31
+ # the loop that performs the iterations internally to reduce
32
+ # overhead. Typically not needed, use the |times| form instead.
33
+ x.report("addition3", "1 + 2")
34
+
35
+ # Really long labels should be formatted correctly
36
+ x.report("addition-test-long-label") { 1 + 2 }
37
+
38
+ x.compare!
39
+ end
40
+
41
+ puts <<-EOD
42
+ Typical results will show addition2 & addition3 to be the most performant, and
43
+ they should perform reasonably similarly. You should see addition and
44
+ addition-test-long-label to perform very similarly to each other (as they are
45
+ running the same test, just with different labels), and they should both run in
46
+ the neighborhood of 3.5 times slower than addition2 and addition3."
47
+ EOD
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Benchmark
2
4
  # Functionality of performaing comparison between reports.
3
5
  #
@@ -24,46 +26,80 @@ module Benchmark
24
26
  # Reduce using to_proc: 247295.4 i/s - 1.13x slower
25
27
  #
26
28
  # Besides regular Calculating report, this will also indicates which one is slower.
29
+ #
30
+ # +x.compare!+ also takes an +order: :baseline+ option.
31
+ #
32
+ # Example:
33
+ # > Benchmark.ips do |x|
34
+ # x.report('Reduce using block') { [*1..10].reduce { |sum, n| sum + n } }
35
+ # x.report('Reduce using tag') { [*1..10].reduce(:+) }
36
+ # x.report('Reduce using to_proc') { [*1..10].reduce(&:+) }
37
+ # x.compare!(order: :baseline)
38
+ # end
39
+ #
40
+ # Calculating -------------------------------------
41
+ # Reduce using block 886.202k (± 2.2%) i/s - 4.521M in 5.103774s
42
+ # Reduce using tag 1.821M (± 1.6%) i/s - 9.111M in 5.004183s
43
+ # Reduce using to_proc 895.948k (± 1.6%) i/s - 4.528M in 5.055368s
44
+ #
45
+ # Comparison:
46
+ # Reduce using block: 886202.5 i/s
47
+ # Reduce using tag: 1821055.0 i/s - 2.05x (± 0.00) faster
48
+ # Reduce using to_proc: 895948.1 i/s - same-ish: difference falls within error
49
+ #
50
+ # The first report is considered the baseline against which other reports are compared.
27
51
  module Compare
28
52
 
29
53
  # Compare between reports, prints out facts of each report:
30
54
  # runtime, comparative speed difference.
31
- # @param reports [Array<Report>] Reports to compare.
32
- def compare(*reports)
33
- return if reports.size < 2
55
+ # @param entries [Array<Report::Entry>] Reports to compare.
56
+ def compare(*entries, order: :fastest)
57
+ return if entries.size < 2
34
58
 
35
- iter = false
36
- sorted = reports.sort do |a,b|
37
- if a.respond_to? :ips
38
- iter = true
39
- b.ips <=> a.ips
40
- else
41
- a.runtime <=> b.runtime
42
- end
59
+ case order
60
+ when :baseline
61
+ baseline = entries.shift
62
+ sorted = entries.sort_by{ |e| e.stats.central_tendency }.reverse
63
+ when :fastest
64
+ sorted = entries.sort_by{ |e| e.stats.central_tendency }.reverse
65
+ baseline = sorted.shift
66
+ else
67
+ raise ArgumentError, "Unknwon order: #{order.inspect}"
43
68
  end
44
69
 
45
- best = sorted.shift
46
-
47
70
  $stdout.puts "\nComparison:"
48
71
 
49
- if iter
50
- $stdout.printf "%20s: %10.1f i/s\n", best.label, best.ips
51
- else
52
- $stdout.puts "#{best.rjust(20)}: #{best.runtime}s"
53
- end
72
+ $stdout.printf "%20s: %10.1f i/s\n", baseline.label.to_s, baseline.stats.central_tendency
54
73
 
55
74
  sorted.each do |report|
56
75
  name = report.label.to_s
57
76
 
58
- if iter
59
- x = (best.ips.to_f / report.ips.to_f)
60
- $stdout.printf "%20s: %10.1f i/s - %.2fx slower\n", name, report.ips, x
77
+ $stdout.printf "%20s: %10.1f i/s - ", name, report.stats.central_tendency
78
+
79
+ if report.stats.overlaps?(baseline.stats)
80
+ $stdout.print "same-ish: difference falls within error"
81
+ elsif report.stats.central_tendency > baseline.stats.central_tendency
82
+ speedup, error = report.stats.speedup(baseline.stats)
83
+ $stdout.printf "%.2fx ", speedup
84
+ if error
85
+ $stdout.printf " (± %.2f)", error
86
+ end
87
+ $stdout.print " faster"
61
88
  else
62
- x = "%.2f" % (report.ips.to_f / best.ips.to_f)
63
- $stdout.puts "#{name.rjust(20)}: #{report.runtime}s - #{x}x slower"
89
+ slowdown, error = report.stats.slowdown(baseline.stats)
90
+ $stdout.printf "%.2fx ", slowdown
91
+ if error
92
+ $stdout.printf " (± %.2f)", error
93
+ end
94
+ $stdout.print " slower"
64
95
  end
96
+
97
+ $stdout.puts
65
98
  end
66
99
 
100
+ footer = baseline.stats.footer
101
+ $stdout.puts footer.rjust(40) if footer
102
+
67
103
  $stdout.puts
68
104
  end
69
105
  end