benchmark-ips 2.13.0 → 2.15.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 +4 -4
- data/History.md +12 -1
- data/README.md +30 -21
- data/examples/quick.rb +17 -0
- data/lib/benchmark/compare.rb +5 -3
- data/lib/benchmark/ips/job/stream_report.rb +4 -16
- data/lib/benchmark/ips/job.rb +20 -10
- data/lib/benchmark/ips/report.rb +18 -8
- data/lib/benchmark/ips/share.rb +1 -1
- data/lib/benchmark/ips/stats/sd.rb +2 -2
- data/lib/benchmark/ips.rb +49 -7
- data/lib/benchmark/timing.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 941e6893612b6307694098b25ebe3cc688dac27020c98cf76d603ead0bd72299
|
|
4
|
+
data.tar.gz: 622715bcc49a8e11c1c6285b35745b9115417e1055b8dc394ca6f5ba07186b66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0e5c2205809523369329ea675f095dc62cefa330e6adb6005b12a6ff4f4d5cfd38ffc16fe819761e4ed10a2c41b1100af8304c3a038383d2377700436873bbb
|
|
7
|
+
data.tar.gz: 318217090715cb2a541606ef8ab91087aec9238ffa0d6b29d5b2b1eeebc2e5d0a725856b59ded62081f1135f2a8bb916c25a31d604c0824accaf67e46ecfab8f
|
data/History.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
### 2.14.0 / 2024-09-08
|
|
2
|
+
|
|
3
|
+
* Feature
|
|
4
|
+
* Adds Benchmark::IPS.quick_compare.
|
|
5
|
+
* Adds absolute duration of each iteration to compare output.
|
|
6
|
+
|
|
7
|
+
### 2.13.0 / 2023-12-12
|
|
8
|
+
|
|
9
|
+
* Feature
|
|
10
|
+
* Prints ruby version at top of report.
|
|
11
|
+
|
|
1
12
|
### 2.12.0 / 2023-03-08
|
|
2
13
|
|
|
3
14
|
* Feature
|
|
@@ -187,7 +198,7 @@ Add missing files
|
|
|
187
198
|
* 1 minor fix:
|
|
188
199
|
* Don't send label through printf so that % work directly
|
|
189
200
|
|
|
190
|
-
* 1
|
|
201
|
+
* 1 documentation changes:
|
|
191
202
|
* Use HEREDOC and wrap at 80 chars for example result description
|
|
192
203
|
|
|
193
204
|
* 1 usage fix:
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* home :: https://github.com/evanphx/benchmark-ips
|
|
5
5
|
|
|
6
6
|
[](http://badge.fury.io/rb/benchmark-ips)
|
|
7
|
-
[](https://github.com/evanphx/benchmark-ips/actions/workflows/ci.yml)
|
|
8
8
|
[](http://inch-ci.org/github/evanphx/benchmark-ips)
|
|
9
9
|
|
|
10
10
|
* https://github.com/evanphx/benchmark-ips
|
|
@@ -27,11 +27,7 @@ require 'benchmark/ips'
|
|
|
27
27
|
Benchmark.ips do |x|
|
|
28
28
|
# Configure the number of seconds used during
|
|
29
29
|
# the warmup phase (default 2) and calculation phase (default 5)
|
|
30
|
-
x.config(:
|
|
31
|
-
|
|
32
|
-
# These parameters can also be configured this way
|
|
33
|
-
x.time = 5
|
|
34
|
-
x.warmup = 2
|
|
30
|
+
x.config(warmup: 2, time: 5)
|
|
35
31
|
|
|
36
32
|
# Typical mode, runs the block as many times as it can
|
|
37
33
|
x.report("addition") { 1 + 2 }
|
|
@@ -43,8 +39,9 @@ Benchmark.ips do |x|
|
|
|
43
39
|
x.report("addition2") do |times|
|
|
44
40
|
i = 0
|
|
45
41
|
while i < times
|
|
46
|
-
1 + 2
|
|
47
42
|
i += 1
|
|
43
|
+
|
|
44
|
+
1 + 2
|
|
48
45
|
end
|
|
49
46
|
end
|
|
50
47
|
|
|
@@ -64,24 +61,24 @@ end
|
|
|
64
61
|
This will generate the following report:
|
|
65
62
|
|
|
66
63
|
```
|
|
67
|
-
|
|
68
|
-
addition
|
|
69
|
-
addition2
|
|
70
|
-
addition3
|
|
64
|
+
Warming up --------------------------------------
|
|
65
|
+
addition 3.572M i/100ms
|
|
66
|
+
addition2 3.672M i/100ms
|
|
67
|
+
addition3 3.677M i/100ms
|
|
71
68
|
addition-test-long-label
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
addition
|
|
75
|
-
addition2
|
|
76
|
-
addition3
|
|
69
|
+
3.511M i/100ms
|
|
70
|
+
Calculating -------------------------------------
|
|
71
|
+
addition 36.209M (± 2.8%) i/s (27.62 ns/i) - 182.253M in 5.037433s
|
|
72
|
+
addition2 36.552M (± 7.8%) i/s (27.36 ns/i) - 183.541M in 5.069987s
|
|
73
|
+
addition3 36.639M (± 4.8%) i/s (27.29 ns/i) - 182.994M in 5.009234s
|
|
77
74
|
addition-test-long-label
|
|
78
|
-
|
|
75
|
+
36.164M (± 5.8%) i/s (27.65 ns/i) - 181.312M in 5.038364s
|
|
79
76
|
|
|
80
77
|
Comparison:
|
|
81
|
-
addition2:
|
|
82
|
-
addition3:
|
|
83
|
-
addition-test-long-label:
|
|
84
|
-
addition:
|
|
78
|
+
addition2: 36558904.5 i/s
|
|
79
|
+
addition3: 36359284.0 i/s - same-ish: difference falls within error
|
|
80
|
+
addition-test-long-label: 36135428.8 i/s - same-ish: difference falls within error
|
|
81
|
+
addition: 34666931.3 i/s - same-ish: difference falls within error
|
|
85
82
|
```
|
|
86
83
|
|
|
87
84
|
Benchmark/ips will report the number of iterations per second for a given block
|
|
@@ -94,6 +91,18 @@ One benefit to using this method is benchmark-ips automatically determines the
|
|
|
94
91
|
data points for testing our code, so we can focus on the results instead of
|
|
95
92
|
guessing iteration counts as we do with the traditional Benchmark library.
|
|
96
93
|
|
|
94
|
+
You can also use `ips_quick` to save a few lines of code:
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
Benchmark.ips_quick(:upcase, :downcase, on: "hello") # runs a suite comparing "hello".upcase and "hello".downcase
|
|
98
|
+
|
|
99
|
+
def first; MyJob.perform(1); end
|
|
100
|
+
def second; MyJobOptimized.perform(1); end
|
|
101
|
+
Benchmark.ips_quick(:first, :second) # compares :first and :second
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This adds a very small amount of overhead, which may be significant (i.e. ips_quick will understate the difference) if you're microbenchmarking things that can do over 1 million iterations per second. In that case, you're better off using the full format.
|
|
105
|
+
|
|
97
106
|
### Custom Suite
|
|
98
107
|
|
|
99
108
|
Pass a custom suite to disable garbage collection during benchmark:
|
data/examples/quick.rb
ADDED
data/lib/benchmark/compare.rb
CHANGED
|
@@ -56,6 +56,8 @@ module Benchmark
|
|
|
56
56
|
def compare(*entries, order: :fastest)
|
|
57
57
|
return if entries.size < 2
|
|
58
58
|
|
|
59
|
+
max_width = entries.map { |e| e.label.to_s.size }.max
|
|
60
|
+
|
|
59
61
|
case order
|
|
60
62
|
when :baseline
|
|
61
63
|
baseline = entries.shift
|
|
@@ -64,17 +66,17 @@ module Benchmark
|
|
|
64
66
|
sorted = entries.sort_by{ |e| e.stats.central_tendency }.reverse
|
|
65
67
|
baseline = sorted.shift
|
|
66
68
|
else
|
|
67
|
-
raise ArgumentError, "
|
|
69
|
+
raise ArgumentError, "Unknown order: #{order.inspect}"
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
$stdout.puts "\nComparison:"
|
|
71
73
|
|
|
72
|
-
$stdout.printf "
|
|
74
|
+
$stdout.printf "%#{max_width}s: %10.1f i/s\n", baseline.label.to_s, baseline.stats.central_tendency
|
|
73
75
|
|
|
74
76
|
sorted.each do |report|
|
|
75
77
|
name = report.label.to_s
|
|
76
78
|
|
|
77
|
-
$stdout.printf "
|
|
79
|
+
$stdout.printf "%#{max_width}s: %10.1f i/s - ", name, report.stats.central_tendency
|
|
78
80
|
|
|
79
81
|
if report.stats.overlaps?(baseline.stats)
|
|
80
82
|
$stdout.print "same-ish: difference falls within error"
|
|
@@ -2,9 +2,10 @@ module Benchmark
|
|
|
2
2
|
module IPS
|
|
3
3
|
class Job
|
|
4
4
|
class StreamReport
|
|
5
|
-
def initialize(stream = $stdout)
|
|
5
|
+
def initialize(job, stream = $stdout)
|
|
6
6
|
@last_item = nil
|
|
7
7
|
@out = stream
|
|
8
|
+
@job = job
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def start_warming
|
|
@@ -17,8 +18,9 @@ module Benchmark
|
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def warming(label, _warmup)
|
|
20
|
-
@out.print rjust(
|
|
21
|
+
@out.print label.to_s.rjust(@job.max_width)
|
|
21
22
|
end
|
|
23
|
+
alias_method :running, :warming
|
|
22
24
|
|
|
23
25
|
def warmup_stats(_warmup_time_us, timing)
|
|
24
26
|
case format
|
|
@@ -29,8 +31,6 @@ module Benchmark
|
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
alias_method :running, :warming
|
|
33
|
-
|
|
34
34
|
def add_report(item, caller)
|
|
35
35
|
@out.puts " #{item.body}"
|
|
36
36
|
@last_item = item
|
|
@@ -48,18 +48,6 @@ module Benchmark
|
|
|
48
48
|
def format
|
|
49
49
|
Benchmark::IPS.options[:format]
|
|
50
50
|
end
|
|
51
|
-
|
|
52
|
-
# Add padding to label's right if label's length < 20,
|
|
53
|
-
# Otherwise add a new line and 20 whitespaces.
|
|
54
|
-
# @return [String] Right justified label.
|
|
55
|
-
def rjust(label)
|
|
56
|
-
label = label.to_s
|
|
57
|
-
if label.size > 20
|
|
58
|
-
"#{label}\n#{' ' * 20}"
|
|
59
|
-
else
|
|
60
|
-
label.rjust(20)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
51
|
end
|
|
64
52
|
end
|
|
65
53
|
end
|
data/lib/benchmark/ips/job.rb
CHANGED
|
@@ -9,7 +9,8 @@ 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
|
-
|
|
12
|
+
# Keep iterations below this to avoid overflow to 64-bit long or Bignum
|
|
13
|
+
MAX_ITERATIONS = 1 << 30
|
|
13
14
|
|
|
14
15
|
# Two-element arrays, consisting of label and block pairs.
|
|
15
16
|
# @return [Array<Entry>] list of entries
|
|
@@ -51,6 +52,10 @@ module Benchmark
|
|
|
51
52
|
# @return [Integer]
|
|
52
53
|
attr_accessor :confidence
|
|
53
54
|
|
|
55
|
+
# The maximum label width
|
|
56
|
+
# @return [Integer]
|
|
57
|
+
attr_reader :max_width
|
|
58
|
+
|
|
54
59
|
# Silence output
|
|
55
60
|
# @return [Boolean]
|
|
56
61
|
def quiet
|
|
@@ -72,6 +77,7 @@ module Benchmark
|
|
|
72
77
|
@compare_order = :fastest
|
|
73
78
|
@held_path = nil
|
|
74
79
|
@held_results = nil
|
|
80
|
+
@max_width = 20 # automatically computed as entries are added
|
|
75
81
|
|
|
76
82
|
@timing = Hash.new 1 # default to 1 in case warmup isn't run
|
|
77
83
|
@full_report = Report.new
|
|
@@ -85,7 +91,7 @@ module Benchmark
|
|
|
85
91
|
@stats = :sd
|
|
86
92
|
@confidence = 95
|
|
87
93
|
|
|
88
|
-
@out = MultiReport.new(StreamReport.new)
|
|
94
|
+
@out = MultiReport.new(StreamReport.new(self))
|
|
89
95
|
end
|
|
90
96
|
|
|
91
97
|
# Job configuration options, set +@warmup+ and +@time+.
|
|
@@ -106,7 +112,7 @@ module Benchmark
|
|
|
106
112
|
if val # remove instances of StreamReport
|
|
107
113
|
@out.quiet!
|
|
108
114
|
else # ensure there is an instance of StreamReport
|
|
109
|
-
@out << StreamReport.new if @out.quiet?
|
|
115
|
+
@out << StreamReport.new(self) if @out.quiet?
|
|
110
116
|
end
|
|
111
117
|
end
|
|
112
118
|
|
|
@@ -180,6 +186,8 @@ module Benchmark
|
|
|
180
186
|
action = str || blk
|
|
181
187
|
raise ArgumentError, "no block or string" unless action
|
|
182
188
|
|
|
189
|
+
@max_width = label.size if label.size > @max_width
|
|
190
|
+
|
|
183
191
|
@list.push Entry.new(label, action)
|
|
184
192
|
self
|
|
185
193
|
end
|
|
@@ -203,7 +211,7 @@ module Benchmark
|
|
|
203
211
|
(after.to_f - before.to_f) * MICROSECONDS_PER_SECOND
|
|
204
212
|
end
|
|
205
213
|
|
|
206
|
-
# Calculate the
|
|
214
|
+
# Calculate the iterations per second given the number
|
|
207
215
|
# of cycles run and the time in microseconds that elapsed.
|
|
208
216
|
# @param [Integer] cycles Cycles.
|
|
209
217
|
# @param [Integer] time_us Time in microsecond.
|
|
@@ -219,7 +227,7 @@ module Benchmark
|
|
|
219
227
|
JSON.load(IO.read(@held_path)).each do |result|
|
|
220
228
|
@held_results[result['item']] = result
|
|
221
229
|
create_report(result['item'], result['measured_us'], result['iter'],
|
|
222
|
-
create_stats(result['samples']), result['cycles'])
|
|
230
|
+
create_stats(result['samples'], result['measured_us'], result['iter']), result['cycles'])
|
|
223
231
|
end
|
|
224
232
|
end
|
|
225
233
|
|
|
@@ -289,11 +297,13 @@ module Benchmark
|
|
|
289
297
|
|
|
290
298
|
# If the number of cycles would go outside the 32-bit signed integers range
|
|
291
299
|
# then exit the loop to avoid overflows and start the 100ms warmup runs
|
|
292
|
-
break if cycles >=
|
|
300
|
+
break if cycles >= MAX_ITERATIONS
|
|
293
301
|
cycles *= 2
|
|
294
302
|
end while Timing.now + warmup_time_us * 2 < target
|
|
295
303
|
|
|
296
|
-
|
|
304
|
+
per_100ms = cycles_per_100ms warmup_time_us, warmup_iter
|
|
305
|
+
# Not [per_100ms, MAX_ITERATIONS].min as that can promote the result to long
|
|
306
|
+
cycles = per_100ms > MAX_ITERATIONS ? MAX_ITERATIONS : per_100ms
|
|
297
307
|
@timing[item] = cycles
|
|
298
308
|
|
|
299
309
|
# Run for the remaining of warmup in a similar way as #run_benchmark.
|
|
@@ -349,7 +359,7 @@ module Benchmark
|
|
|
349
359
|
iterations_per_sec cycles, time_us
|
|
350
360
|
}
|
|
351
361
|
|
|
352
|
-
rep = create_report(item.label, measured_us, iter, create_stats(samples), cycles)
|
|
362
|
+
rep = create_report(item.label, measured_us, iter, create_stats(samples, measured_us, iter), cycles)
|
|
353
363
|
|
|
354
364
|
if (final_time - target).abs >= (@time.to_f * MAX_TIME_SKEW)
|
|
355
365
|
rep.show_total_time!
|
|
@@ -361,10 +371,10 @@ module Benchmark
|
|
|
361
371
|
end
|
|
362
372
|
end
|
|
363
373
|
|
|
364
|
-
def create_stats(samples)
|
|
374
|
+
def create_stats(samples, measured_us, iterations)
|
|
365
375
|
case @stats
|
|
366
376
|
when :sd
|
|
367
|
-
Stats::SD.new(samples)
|
|
377
|
+
Stats::SD.new(samples, measured_us, iterations)
|
|
368
378
|
when :bootstrap
|
|
369
379
|
Stats::Bootstrap.new(samples, @confidence)
|
|
370
380
|
else
|
data/lib/benchmark/ips/report.rb
CHANGED
|
@@ -62,7 +62,7 @@ module Benchmark
|
|
|
62
62
|
|
|
63
63
|
# Control if the total time the job took is reported.
|
|
64
64
|
# Typically this value is not significant because it's very
|
|
65
|
-
# close to the expected time, so it's
|
|
65
|
+
# close to the expected time, so it's suppressed by default.
|
|
66
66
|
def show_total_time!
|
|
67
67
|
@show_total_time = true
|
|
68
68
|
end
|
|
@@ -86,23 +86,33 @@ module Benchmark
|
|
|
86
86
|
# percentage of standard deviation, iterations in runtime.
|
|
87
87
|
# @return [String] Left justified body.
|
|
88
88
|
def body
|
|
89
|
+
per_iter = (" (%s/i)" % Helpers.humanize_duration(1_000_000_000 / @stats.central_tendency)).rjust(15)
|
|
90
|
+
|
|
89
91
|
case Benchmark::IPS.options[:format]
|
|
90
92
|
when :human
|
|
91
|
-
|
|
93
|
+
central_tendency = Helpers.scale(@stats.central_tendency)
|
|
94
|
+
error_percentage = @stats.error_percentage
|
|
95
|
+
left =
|
|
96
|
+
if error_percentage > 99.9
|
|
97
|
+
"%s (± Inf%%) i/s" % [central_tendency]
|
|
98
|
+
else
|
|
99
|
+
"%s (±%4.1f%%) i/s" % [central_tendency, @stats.error_percentage]
|
|
100
|
+
end.ljust(20)
|
|
101
|
+
|
|
92
102
|
iters = Helpers.scale(@iterations)
|
|
93
103
|
|
|
94
104
|
if @show_total_time
|
|
95
|
-
left
|
|
105
|
+
left + per_iter + (" - %s in %10.6fs" % [iters, runtime])
|
|
96
106
|
else
|
|
97
|
-
left
|
|
107
|
+
left + per_iter + (" - %s" % iters)
|
|
98
108
|
end
|
|
99
109
|
else
|
|
100
|
-
left = "%10.1f (±%.1f%%) i/s" % [@stats.central_tendency, @stats.error_percentage]
|
|
110
|
+
left = ("%10.1f (±%.1f%%) i/s" % [@stats.central_tendency, @stats.error_percentage]).ljust(20)
|
|
101
111
|
|
|
102
112
|
if @show_total_time
|
|
103
|
-
left
|
|
113
|
+
left + per_iter + (" - %10d in %10.6fs" % [@iterations, runtime])
|
|
104
114
|
else
|
|
105
|
-
left
|
|
115
|
+
left + per_iter + (" - %10d" % @iterations)
|
|
106
116
|
end
|
|
107
117
|
end
|
|
108
118
|
end
|
|
@@ -113,7 +123,7 @@ module Benchmark
|
|
|
113
123
|
@label.to_s.rjust(20)
|
|
114
124
|
end
|
|
115
125
|
|
|
116
|
-
# Return string
|
|
126
|
+
# Return string representation of Entry object.
|
|
117
127
|
# @return [String] Header and body.
|
|
118
128
|
def to_s
|
|
119
129
|
"#{header} #{body}"
|
data/lib/benchmark/ips/share.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Benchmark
|
|
|
17
17
|
base = (ENV['SHARE_URL'] || DEFAULT_URL)
|
|
18
18
|
url = URI(File.join(base, "reports"))
|
|
19
19
|
|
|
20
|
-
req = Net::HTTP::Post.new(url)
|
|
20
|
+
req = Net::HTTP::Post.new(url, initheader = {'Content-Type' =>'application/json'})
|
|
21
21
|
|
|
22
22
|
data = {
|
|
23
23
|
"entries" => @report.data,
|
|
@@ -6,9 +6,9 @@ module Benchmark
|
|
|
6
6
|
include StatsMetric
|
|
7
7
|
attr_reader :error, :samples
|
|
8
8
|
|
|
9
|
-
def initialize(samples)
|
|
9
|
+
def initialize(samples, measured_us, iterations)
|
|
10
10
|
@samples = samples
|
|
11
|
-
@mean = Timing.
|
|
11
|
+
@mean = Timing::MICROSECONDS_PER_SECOND * (iterations.to_f / measured_us)
|
|
12
12
|
@error = Timing.stddev(samples, @mean).round
|
|
13
13
|
end
|
|
14
14
|
|
data/lib/benchmark/ips.rb
CHANGED
|
@@ -13,14 +13,17 @@ require 'benchmark/ips/job'
|
|
|
13
13
|
# Performance benchmarking library
|
|
14
14
|
module Benchmark
|
|
15
15
|
# Benchmark in iterations per second, no more guessing!
|
|
16
|
-
#
|
|
16
|
+
#
|
|
17
|
+
# See Benchmark.ips for documentation on using this gem~
|
|
18
|
+
#
|
|
19
|
+
# @see {https://github.com/evanphx/benchmark-ips}
|
|
17
20
|
module IPS
|
|
18
21
|
|
|
19
22
|
# Benchmark-ips Gem version.
|
|
20
|
-
VERSION = "2.
|
|
23
|
+
VERSION = "2.15.0"
|
|
21
24
|
|
|
22
25
|
# CODENAME of current version.
|
|
23
|
-
CODENAME = "
|
|
26
|
+
CODENAME = "Harmonic Nice"
|
|
24
27
|
|
|
25
28
|
# Measure code in block, each code's benchmarked result will display in
|
|
26
29
|
# iteration per second with standard deviation in given time.
|
|
@@ -73,6 +76,32 @@ module Benchmark
|
|
|
73
76
|
report
|
|
74
77
|
end
|
|
75
78
|
|
|
79
|
+
# Quickly compare multiple methods on the same object.
|
|
80
|
+
# @param methods [Symbol...] A list of method names (as symbols) to compare.
|
|
81
|
+
# @param receiver [Object] The object on which to call the methods. Defaults to Kernel.
|
|
82
|
+
# @param opts [Hash] Additional options for customizing the benchmark.
|
|
83
|
+
# @option opts [Integer] :warmup The number of seconds to warm up the benchmark.
|
|
84
|
+
# @option opts [Integer] :time The number of seconds to run the benchmark.
|
|
85
|
+
#
|
|
86
|
+
# @example Compare String#upcase and String#downcase
|
|
87
|
+
# ips_quick(:upcase, :downcase, on: "hello")
|
|
88
|
+
#
|
|
89
|
+
# @example Compare two methods you just defined, with a custom warmup.
|
|
90
|
+
# def add; 1+1; end
|
|
91
|
+
# def sub; 2-1; end
|
|
92
|
+
# ips_quick(:add, :sub, warmup: 10)
|
|
93
|
+
def ips_quick(*methods, on: Kernel, **opts)
|
|
94
|
+
ips(opts) do |x|
|
|
95
|
+
x.compare!
|
|
96
|
+
|
|
97
|
+
methods.each do |name|
|
|
98
|
+
x.report(name) do |iter|
|
|
99
|
+
iter.times { on.__send__ name }
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
76
105
|
# Set options for running the benchmarks.
|
|
77
106
|
# :format => [:human, :raw]
|
|
78
107
|
# :human format narrows precision and scales results for readability
|
|
@@ -83,20 +112,33 @@ module Benchmark
|
|
|
83
112
|
|
|
84
113
|
module Helpers
|
|
85
114
|
SUFFIXES = ['', 'k', 'M', 'B', 'T', 'Q'].freeze
|
|
86
|
-
|
|
115
|
+
|
|
87
116
|
def scale(value)
|
|
88
|
-
scale = (Math.log10(value) / 3).to_i
|
|
117
|
+
scale = (Math.log10(value) / 3).to_i
|
|
89
118
|
scale = 0 if scale < 0 || scale >= SUFFIXES.size
|
|
90
119
|
suffix = SUFFIXES[scale]
|
|
91
120
|
scaled_value = value.to_f / (1000 ** scale)
|
|
92
|
-
|
|
121
|
+
|
|
93
122
|
"%10.3f#{suffix}" % scaled_value
|
|
94
123
|
end
|
|
95
124
|
module_function :scale
|
|
125
|
+
|
|
126
|
+
def humanize_duration(duration_ns)
|
|
127
|
+
if duration_ns < 1000
|
|
128
|
+
"%.2f ns" % duration_ns
|
|
129
|
+
elsif duration_ns < 1_000_000
|
|
130
|
+
"%.2f μs" % (duration_ns / 1000)
|
|
131
|
+
elsif duration_ns < 1_000_000_000
|
|
132
|
+
"%.2f ms" % (duration_ns / 1_000_000)
|
|
133
|
+
else
|
|
134
|
+
"%.2f s" % (duration_ns / 1_000_000_000)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
module_function :humanize_duration
|
|
96
138
|
end
|
|
97
139
|
end
|
|
98
140
|
|
|
99
|
-
extend Benchmark::IPS # make ips available as module-level method
|
|
141
|
+
extend Benchmark::IPS # make ips/ips_quick available as module-level method
|
|
100
142
|
|
|
101
143
|
##
|
|
102
144
|
# :singleton-method: ips
|
data/lib/benchmark/timing.rb
CHANGED
|
@@ -4,9 +4,9 @@ module Benchmark
|
|
|
4
4
|
# Microseconds per second.
|
|
5
5
|
MICROSECONDS_PER_SECOND = 1_000_000
|
|
6
6
|
|
|
7
|
-
# Calculate
|
|
7
|
+
# Calculate arithmetic mean of given numbers.
|
|
8
8
|
# @param [Array] samples Samples to calculate mean.
|
|
9
|
-
# @return [Float] Mean of given
|
|
9
|
+
# @return [Float] Mean of given numbers.
|
|
10
10
|
def self.mean(samples)
|
|
11
11
|
sum = samples.inject(:+)
|
|
12
12
|
sum / samples.size
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: benchmark-ips
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Evan Phoenix
|
|
@@ -53,6 +53,7 @@ files:
|
|
|
53
53
|
- README.md
|
|
54
54
|
- examples/advanced.rb
|
|
55
55
|
- examples/hold.rb
|
|
56
|
+
- examples/quick.rb
|
|
56
57
|
- examples/save.rb
|
|
57
58
|
- examples/simple.rb
|
|
58
59
|
- lib/benchmark/compare.rb
|
|
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
88
89
|
- !ruby/object:Gem::Version
|
|
89
90
|
version: '0'
|
|
90
91
|
requirements: []
|
|
91
|
-
rubygems_version: 3.
|
|
92
|
+
rubygems_version: 3.4.20
|
|
92
93
|
signing_key:
|
|
93
94
|
specification_version: 4
|
|
94
95
|
summary: A iterations per second enhancement to Benchmark.
|