benchmark-ips 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +11 -0
- data/Manifest.txt +0 -1
- data/README.md +24 -12
- data/lib/benchmark/compare.rb +34 -6
- data/lib/benchmark/ips.rb +41 -2
- data/lib/benchmark/ips/job.rb +98 -24
- data/lib/benchmark/ips/report.rb +90 -6
- data/lib/benchmark/timing.rb +16 -0
- data/test/test_benchmark_ips.rb +1 -1
- metadata +9 -10
- data/lib/benchmark/helpers.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b0795c8f86b241fbf0e02d13401e209cac488ad
|
4
|
+
data.tar.gz: bd46b20f496f074e93c33a378da27e7ae225fe62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7d3b4ca509f2fcca1ec8f5eef9b0f2d0e2bc218abe7d69b359f9c41a64767dc19b16f8be1ee6bafd3c33d1f738ae0cc54fdbb12922d67cecd0092f885dc8c42
|
7
|
+
data.tar.gz: 3ca470bf622922c813cf8f6f6a82a4124b681d172cb1662488507a020ea314244ad012ee6ae724c81509135b8ce24539da4492dc8f0a7711c80b98f98974310d
|
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
=== 2.1.0 / 2014-11-10
|
2
|
+
|
3
|
+
* Documentation changes:
|
4
|
+
* Many documentation fixes by Juanito Fatas!
|
5
|
+
* Minor readme fix by Will Leinweber
|
6
|
+
|
7
|
+
* 2 minor features:
|
8
|
+
* Displaying the total runtime for a job is suppressed unless interesting
|
9
|
+
* Formatting of large values improved (human vs raw mode)
|
10
|
+
* Contributed by Charles Oliver Nutter
|
11
|
+
|
1
12
|
=== 2.0.0 / 2014-06-18
|
2
13
|
|
3
14
|
* The 'Davy Stevenson' release!
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
[![
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/benchmark-ips.svg)](http://badge.fury.io/rb/benchmark-ips)
|
2
|
+
[![Build Status](https://secure.travis-ci.org/evanphx/benchmark-ips.svg)](http://travis-ci.org/evanphx/benchmark-ips)
|
3
|
+
[![Inline docs](http://inch-ci.org/github/evanphx/benchmark-ips.svg)](http://inch-ci.org/github/evanphx/benchmark-ips)
|
2
4
|
|
3
5
|
# benchmark-ips
|
4
6
|
|
5
|
-
*
|
7
|
+
* https://github.com/evanphx/benchmark-ips
|
8
|
+
|
9
|
+
* [documentation](http://rubydoc.info/gems/benchmark-ips)
|
6
10
|
|
7
11
|
## DESCRIPTION:
|
8
12
|
|
9
|
-
A iterations per second enhancement to Benchmark
|
13
|
+
A iterations per second enhancement to Benchmark.
|
10
14
|
|
11
15
|
## FEATURES/PROBLEMS:
|
12
16
|
|
@@ -21,7 +25,7 @@ require 'benchmark/ips'
|
|
21
25
|
|
22
26
|
Benchmark.ips do |x|
|
23
27
|
# Configure the number of seconds used during
|
24
|
-
# the warmup phase and calculation phase
|
28
|
+
# the warmup phase (default 2) and calculation phase (default 5)
|
25
29
|
x.config(:time => 5, :warmup => 2)
|
26
30
|
|
27
31
|
# These parameters can also be configured this way
|
@@ -60,13 +64,23 @@ This will generate the following report:
|
|
60
64
|
|
61
65
|
```
|
62
66
|
Calculating -------------------------------------
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
addition 71254 i/100ms
|
68
|
+
addition2 68658 i/100ms
|
69
|
+
addition3 83079 i/100ms
|
70
|
+
addition-test-long-label
|
71
|
+
70129 i/100ms
|
66
72
|
-------------------------------------------------
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
addition 4955278.9 (±8.7%) i/s - 24155106 in 5.002163s
|
74
|
+
addition2 24011974.8 (±9.5%) i/s - 114246912 in 4.995446s
|
75
|
+
addition3 23958619.8 (±9.9%) i/s - 115064415 in 4.996349s
|
76
|
+
addition-test-long-label
|
77
|
+
5014756.0 (±9.1%) i/s - 24545150 in 5.009754s
|
78
|
+
|
79
|
+
Comparison:
|
80
|
+
addition2: 24011974.8 i/s
|
81
|
+
addition3: 23958619.8 i/s - 1.00x slower
|
82
|
+
addition-test-long-label: 5014756.0 i/s - 4.79x slower
|
83
|
+
addition: 4955278.9 i/s - 4.85x slower
|
70
84
|
```
|
71
85
|
|
72
86
|
Benchmark/ips will report the number of iterations per second for a given block
|
@@ -96,8 +110,6 @@ After checking out the source, run:
|
|
96
110
|
This task will install any missing dependencies, run the tests/specs,
|
97
111
|
and generate the RDoc.
|
98
112
|
|
99
|
-
Run the example file `bin/benchmark_ips` to test that everything is working properly.
|
100
|
-
|
101
113
|
## LICENSE:
|
102
114
|
|
103
115
|
(The MIT License)
|
data/lib/benchmark/compare.rb
CHANGED
@@ -1,6 +1,34 @@
|
|
1
1
|
module Benchmark
|
2
|
+
# Functionality of performaing comparison between reports.
|
3
|
+
#
|
4
|
+
# Usage:
|
5
|
+
#
|
6
|
+
# Add +x.compare!+ to perform comparison between reports.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# > Benchmark.ips do |x|
|
10
|
+
# x.report('Reduce using tag') { [*1..10].reduce(:+) }
|
11
|
+
# x.report('Reduce using to_proc') { [*1..10].reduce(&:+) }
|
12
|
+
# x.compare!
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# Calculating -------------------------------------
|
16
|
+
# Reduce using tag 19216 i/100ms
|
17
|
+
# Reduce using to_proc 17437 i/100ms
|
18
|
+
# -------------------------------------------------
|
19
|
+
# Reduce using tag 278950.0 (±8.5%) i/s - 1402768 in 5.065112s
|
20
|
+
# Reduce using to_proc 247295.4 (±8.0%) i/s - 1238027 in 5.037299s
|
21
|
+
#
|
22
|
+
# Comparison:
|
23
|
+
# Reduce using tag: 278950.0 i/s
|
24
|
+
# Reduce using to_proc: 247295.4 i/s - 1.13x slower
|
25
|
+
#
|
26
|
+
# Besides regular Calculating report, this will also indicates which one is slower.
|
2
27
|
module Compare
|
3
28
|
|
29
|
+
# Compare between reports, prints out facts of each report:
|
30
|
+
# runtime, comparative speed difference.
|
31
|
+
# @param reports [Array<Report>] Reports to compare.
|
4
32
|
def compare(*reports)
|
5
33
|
return if reports.size < 2
|
6
34
|
|
@@ -16,12 +44,12 @@ module Benchmark
|
|
16
44
|
|
17
45
|
best = sorted.shift
|
18
46
|
|
19
|
-
|
47
|
+
$stdout.puts "\nComparison:"
|
20
48
|
|
21
49
|
if iter
|
22
|
-
|
50
|
+
$stdout.printf "%20s: %10.1f i/s\n", best.label, best.ips
|
23
51
|
else
|
24
|
-
|
52
|
+
$stdout.puts "#{best.rjust(20)}: #{best.runtime}s"
|
25
53
|
end
|
26
54
|
|
27
55
|
sorted.each do |report|
|
@@ -29,14 +57,14 @@ module Benchmark
|
|
29
57
|
|
30
58
|
if iter
|
31
59
|
x = (best.ips.to_f / report.ips.to_f)
|
32
|
-
|
60
|
+
$stdout.printf "%20s: %10.1f i/s - %.2fx slower\n", name, report.ips, x
|
33
61
|
else
|
34
62
|
x = "%.2f" % (report.ips.to_f / best.ips.to_f)
|
35
|
-
|
63
|
+
$stdout.puts "#{name.rjust(20)}: #{report.runtime}s - #{x}x slower"
|
36
64
|
end
|
37
65
|
end
|
38
66
|
|
39
|
-
|
67
|
+
$stdout.puts
|
40
68
|
end
|
41
69
|
end
|
42
70
|
|
data/lib/benchmark/ips.rb
CHANGED
@@ -4,11 +4,23 @@ require 'benchmark/compare'
|
|
4
4
|
require 'benchmark/ips/report'
|
5
5
|
require 'benchmark/ips/job'
|
6
6
|
|
7
|
+
# Performance benchmarking library
|
7
8
|
module Benchmark
|
9
|
+
# Benchmark in iterations per second, no more guessing!
|
10
|
+
# @see https://github.com/evanphx/benchmark-ips
|
8
11
|
module IPS
|
9
|
-
|
12
|
+
|
13
|
+
# Benchmark-ips Gem version.
|
14
|
+
VERSION = "2.1.0"
|
15
|
+
|
16
|
+
# CODENAME of current version.
|
10
17
|
CODENAME = "Springtime Hummingbird Dance"
|
11
18
|
|
19
|
+
# Measure code in block, each code's benchmarked result will display in
|
20
|
+
# iteration per second with standard deviation in given time.
|
21
|
+
# @param time [Integer] Specify how long should benchmark your code in seconds.
|
22
|
+
# @param warmup [Integer] Specify how long should Warmup time run in seconds.
|
23
|
+
# @return [Report]
|
12
24
|
def ips(time=nil, warmup=nil)
|
13
25
|
suite = nil
|
14
26
|
|
@@ -48,7 +60,34 @@ module Benchmark
|
|
48
60
|
|
49
61
|
return job.full_report
|
50
62
|
end
|
63
|
+
|
64
|
+
# Set options for running the benchmarks.
|
65
|
+
# :format => [:human, :raw]
|
66
|
+
# :human format narrows precision and scales results for readability
|
67
|
+
# :raw format displays 6 places of precision and exact iteration counts
|
68
|
+
def self.options
|
69
|
+
@options ||= {:format => :human}
|
70
|
+
end
|
71
|
+
|
72
|
+
module Helpers
|
73
|
+
def scale(value)
|
74
|
+
scale = (Math.log10(value) / 3).to_i
|
75
|
+
suffix = case scale
|
76
|
+
when 1; 'k'
|
77
|
+
when 2; 'M'
|
78
|
+
when 3; 'B'
|
79
|
+
when 4; 'T'
|
80
|
+
when 5; 'Q'
|
81
|
+
else
|
82
|
+
# < 1000 or > 10^15, no scale or suffix
|
83
|
+
scale = 0
|
84
|
+
' '
|
85
|
+
end
|
86
|
+
"%10.3f#{suffix}" % (value.to_f / (1000 ** scale))
|
87
|
+
end
|
88
|
+
module_function :scale
|
89
|
+
end
|
51
90
|
end
|
52
91
|
|
53
|
-
extend Benchmark::IPS
|
92
|
+
extend Benchmark::IPS # make ips available as module-level method
|
54
93
|
end
|
data/lib/benchmark/ips/job.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
module Benchmark
|
2
2
|
module IPS
|
3
|
+
# Benchmark jobs.
|
3
4
|
class Job
|
4
|
-
|
5
|
+
# Microseconds per 100 millisecond.
|
5
6
|
MICROSECONDS_PER_100MS = 100_000
|
7
|
+
# Microseconds per second.
|
6
8
|
MICROSECONDS_PER_SECOND = 1_000_000
|
9
|
+
# The percentage of the expected runtime to allow
|
10
|
+
# before reporting a weird runtime
|
11
|
+
MAX_TIME_SKEW = 0.05
|
7
12
|
|
13
|
+
# Entries in Benchmark Jobs.
|
8
14
|
class Entry
|
15
|
+
# Instantiate the Benchmark::IPS::Job::Entry.
|
16
|
+
# @param label [String] Label of Benchmarked code.
|
17
|
+
# @param action [String, Proc] Code to be benchmarked.
|
18
|
+
# @raise [ArgumentError] Raises when action is not String or not responding to +call+.
|
9
19
|
def initialize(label, action)
|
10
20
|
@label = label
|
11
21
|
|
@@ -30,8 +40,17 @@ module Benchmark
|
|
30
40
|
end
|
31
41
|
end
|
32
42
|
|
33
|
-
|
43
|
+
# The label of benchmarking action.
|
44
|
+
# @return [String] Label of action.
|
45
|
+
attr_reader :label
|
46
|
+
|
47
|
+
# The benchmarking action.
|
48
|
+
# @return [String, Proc] Code to be called, could be String / Proc.
|
49
|
+
attr_reader :action
|
34
50
|
|
51
|
+
# Add padding to label's right if label's length < 20,
|
52
|
+
# Otherwise add a new line and 20 whitespaces.
|
53
|
+
# @return [String] Right justified label.
|
35
54
|
def label_rjust
|
36
55
|
if @label.size > 20
|
37
56
|
"#{@label}\n#{' ' * 20}"
|
@@ -40,10 +59,9 @@ module Benchmark
|
|
40
59
|
end
|
41
60
|
end
|
42
61
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
62
|
+
# Call action by given times, return if +@call_loop+ is present.
|
63
|
+
# @param times [Integer] Times to call +@action+.
|
64
|
+
# @return [Integer] Number of times the +@action+ has been called.
|
47
65
|
def call_times(times)
|
48
66
|
return @action.call(times) if @call_loop
|
49
67
|
|
@@ -56,6 +74,9 @@ module Benchmark
|
|
56
74
|
end
|
57
75
|
end
|
58
76
|
|
77
|
+
# Compile code into +call_times+ method.
|
78
|
+
# @param str [String] Code to be compiled.
|
79
|
+
# @return [Symbol] :call_times.
|
59
80
|
def compile(str)
|
60
81
|
m = (class << self; self; end)
|
61
82
|
code = <<-CODE
|
@@ -69,20 +90,37 @@ module Benchmark
|
|
69
90
|
CODE
|
70
91
|
m.class_eval code
|
71
92
|
end
|
72
|
-
end
|
93
|
+
end # End of Entry
|
94
|
+
|
95
|
+
# class Job
|
73
96
|
|
74
|
-
#
|
97
|
+
# Two-element arrays, consisting of label and block pairs.
|
98
|
+
# @return [Array<Entry>] list of entries
|
75
99
|
attr_reader :list
|
76
100
|
|
77
|
-
#
|
101
|
+
# Determining whether to run comparison utility.
|
102
|
+
# @return [Boolean] true if needs to run compare.
|
78
103
|
attr_reader :compare
|
79
104
|
|
80
|
-
# Report object containing information about the run
|
105
|
+
# Report object containing information about the run.
|
106
|
+
# @return [Report] the report object.
|
81
107
|
attr_reader :full_report
|
82
108
|
|
83
|
-
|
109
|
+
# Storing Iterations in time period.
|
110
|
+
# @return [Hash]
|
84
111
|
attr_reader :timing
|
85
112
|
|
113
|
+
# Warmup time setter and getter (in seconds).
|
114
|
+
# @return [Integer]
|
115
|
+
attr_accessor :warmup
|
116
|
+
|
117
|
+
# Calculation time setter and getter (in seconds).
|
118
|
+
# @return [Integer]
|
119
|
+
attr_accessor :time
|
120
|
+
|
121
|
+
# Instantiate the Benchmark::IPS::Job.
|
122
|
+
# @option opts [Benchmark::Suite] (nil) :suite Specify Benchmark::Suite.
|
123
|
+
# @option opts [Boolean] (false) :quiet Suppress the printing of information.
|
86
124
|
def initialize opts={}
|
87
125
|
@suite = opts[:suite] || nil
|
88
126
|
@quiet = opts[:quiet] || false
|
@@ -92,27 +130,36 @@ module Benchmark
|
|
92
130
|
@timing = {}
|
93
131
|
@full_report = Report.new
|
94
132
|
|
95
|
-
#
|
133
|
+
# Default warmup and calculation time in seconds.
|
96
134
|
@warmup = 2
|
97
135
|
@time = 5
|
98
136
|
end
|
99
137
|
|
138
|
+
# Job configuration options, set +@warmup+ and +@time+.
|
139
|
+
# @option opts [Integer] :warmup Warmup time.
|
140
|
+
# @option opts [Integer] :time Calculation time.
|
100
141
|
def config opts
|
101
142
|
@warmup = opts[:warmup] if opts[:warmup]
|
102
143
|
@time = opts[:time] if opts[:time]
|
103
144
|
end
|
104
145
|
|
146
|
+
# Return true if job needs to be compared.
|
147
|
+
# @return [Boolean] Need to compare?
|
105
148
|
def compare?
|
106
149
|
@compare
|
107
150
|
end
|
108
151
|
|
152
|
+
# Set @compare to true.
|
109
153
|
def compare!
|
110
154
|
@compare = true
|
111
155
|
end
|
112
156
|
|
113
|
-
#
|
114
157
|
# Registers the given label and block pair in the job list.
|
115
|
-
#
|
158
|
+
# @param label [String] Label of benchmarked code.
|
159
|
+
# @param str [String] Code to be benchamrked.
|
160
|
+
# @param blk [Proc] Code to be benchamrked.
|
161
|
+
# @raise [ArgumentError] Raises if str and blk are both present.
|
162
|
+
# @raise [ArgumentError] Raises if str and blk are both absent.
|
116
163
|
def item(label="", str=nil, &blk) # :yield:
|
117
164
|
if blk and str
|
118
165
|
raise ArgumentError, "specify a block and a str, but not both"
|
@@ -126,26 +173,35 @@ module Benchmark
|
|
126
173
|
end
|
127
174
|
alias_method :report, :item
|
128
175
|
|
129
|
-
#
|
130
|
-
# given the number of iterations to run the given time
|
176
|
+
# Calculate the cycles needed to run for approx 100ms,
|
177
|
+
# given the number of iterations to run the given time.
|
178
|
+
# @param [Float] time_msec Each iteration's time in ms.
|
179
|
+
# @param [Integer] iters Iterations.
|
180
|
+
# @return [Integer] Cycles per 100ms.
|
131
181
|
def cycles_per_100ms time_msec, iters
|
132
182
|
cycles = ((MICROSECONDS_PER_100MS / time_msec) * iters).to_i
|
133
183
|
cycles = 1 if cycles <= 0
|
134
184
|
cycles
|
135
185
|
end
|
136
186
|
|
137
|
-
#
|
138
|
-
# before
|
187
|
+
# Calculate the time difference of before and after in microseconds.
|
188
|
+
# @param [Time] before time.
|
189
|
+
# @param [Time] after time.
|
190
|
+
# @return [Float] Time difference of before and after.
|
139
191
|
def time_us before, after
|
140
192
|
(after.to_f - before.to_f) * MICROSECONDS_PER_SECOND
|
141
193
|
end
|
142
194
|
|
143
|
-
#
|
144
|
-
# of cycles run and the time in microseconds that elapsed
|
195
|
+
# Calculate the interations per second given the number
|
196
|
+
# of cycles run and the time in microseconds that elapsed.
|
197
|
+
# @param [Integer] cycles Cycles.
|
198
|
+
# @param [Integer] time_us Time in microsecond.
|
199
|
+
# @return [Float] Iteration per second.
|
145
200
|
def iterations_per_sec cycles, time_us
|
146
201
|
MICROSECONDS_PER_SECOND * (cycles.to_f / time_us.to_f)
|
147
202
|
end
|
148
203
|
|
204
|
+
# Run warmup.
|
149
205
|
def run_warmup
|
150
206
|
@list.each do |item|
|
151
207
|
@suite.warming item.label, @warmup if @suite
|
@@ -172,12 +228,18 @@ module Benchmark
|
|
172
228
|
|
173
229
|
@timing[item] = cycles_per_100ms warmup_time_us, warmup_iter
|
174
230
|
|
175
|
-
|
231
|
+
case Benchmark::IPS.options[:format]
|
232
|
+
when :human
|
233
|
+
$stdout.printf "%s i/100ms\n", Helpers.scale(@timing[item]) unless @quiet
|
234
|
+
else
|
235
|
+
$stdout.printf "%10d i/100ms\n", @timing[item] unless @quiet
|
236
|
+
end
|
176
237
|
|
177
238
|
@suite.warmup_stats warmup_time_us, @timing[item] if @suite
|
178
239
|
end
|
179
240
|
end
|
180
241
|
|
242
|
+
# Run calculation.
|
181
243
|
def run
|
182
244
|
@list.each do |item|
|
183
245
|
@suite.running item.label, @time if @suite
|
@@ -194,7 +256,7 @@ module Benchmark
|
|
194
256
|
|
195
257
|
measurements_us = []
|
196
258
|
|
197
|
-
#
|
259
|
+
# Running this number of cycles should take around 100ms.
|
198
260
|
cycles = @timing[item]
|
199
261
|
|
200
262
|
while Time.now < target
|
@@ -204,7 +266,6 @@ module Benchmark
|
|
204
266
|
|
205
267
|
# If for some reason the timing said this took no time (O_o)
|
206
268
|
# then ignore the iteration entirely and start another.
|
207
|
-
#
|
208
269
|
iter_us = time_us before, after
|
209
270
|
next if iter_us <= 0.0
|
210
271
|
|
@@ -213,6 +274,8 @@ module Benchmark
|
|
213
274
|
measurements_us << iter_us
|
214
275
|
end
|
215
276
|
|
277
|
+
final_time = Time.now
|
278
|
+
|
216
279
|
measured_us = measurements_us.inject(0) { |a,i| a + i }
|
217
280
|
|
218
281
|
all_ips = measurements_us.map { |time_us|
|
@@ -224,20 +287,31 @@ module Benchmark
|
|
224
287
|
|
225
288
|
rep = create_report(item, measured_us, iter, avg_ips, sd_ips, cycles)
|
226
289
|
|
290
|
+
if (final_time - target).abs >= (@time.to_f * MAX_TIME_SKEW)
|
291
|
+
rep.show_total_time!
|
292
|
+
end
|
293
|
+
|
227
294
|
$stdout.puts " #{rep.body}" unless @quiet
|
228
295
|
|
229
296
|
@suite.add_report rep, caller(1).first if @suite
|
230
297
|
end
|
231
298
|
end
|
232
299
|
|
300
|
+
# Run comparison of entries in +@full_report+.
|
233
301
|
def run_comparison
|
234
302
|
@full_report.run_comparison
|
235
303
|
end
|
236
304
|
|
305
|
+
# Create report by add entry to +@full_report+.
|
306
|
+
# @param item [Benchmark::IPS::Job::Entry] Report item.
|
307
|
+
# @param measured_us [Integer] Measured time in microsecond.
|
308
|
+
# @param iter [Integer] Iterations.
|
309
|
+
# @param avg_ips [Float] Average iterations per second.
|
310
|
+
# @param sd_ips [Float] Standard deviation iterations per second.
|
311
|
+
# @param cycles [Integer] Number of Cycles.
|
237
312
|
def create_report(item, measured_us, iter, avg_ips, sd_ips, cycles)
|
238
313
|
@full_report.add_entry item.label, measured_us, iter, avg_ips, sd_ips, cycles
|
239
314
|
end
|
240
|
-
|
241
315
|
end
|
242
316
|
end
|
243
317
|
end
|
data/lib/benchmark/ips/report.rb
CHANGED
@@ -1,10 +1,21 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
module Benchmark
|
3
4
|
module IPS
|
5
|
+
|
6
|
+
# Report contains benchamrking entries.
|
7
|
+
# Perform operations like add new entry, run comparison between entries.
|
4
8
|
class Report
|
5
9
|
|
10
|
+
# Represents benchmarking code data for Report.
|
6
11
|
class Entry
|
7
|
-
|
12
|
+
# Instantiate the Benchmark::IPS::Report::Entry.
|
13
|
+
# @param [String] label Label of entry.
|
14
|
+
# @param [Integer] us Measured time in microsecond.
|
15
|
+
# @param [Integer] iters Iterations.
|
16
|
+
# @param [Float] ips Iterations per second.
|
17
|
+
# @param [Float] ips_sd Standard deviation of iterations per second.
|
18
|
+
# @param [Integer] cycles Number of Cycles.
|
8
19
|
def initialize(label, us, iters, ips, ips_sd, cycles)
|
9
20
|
@label = label
|
10
21
|
@microseconds = us
|
@@ -12,53 +23,126 @@ module Benchmark
|
|
12
23
|
@ips = ips
|
13
24
|
@ips_sd = ips_sd
|
14
25
|
@measurement_cycle = cycles
|
26
|
+
@show_total_time = false
|
15
27
|
end
|
16
28
|
|
17
|
-
|
29
|
+
# Label of entry.
|
30
|
+
# @return [String] the label of entry.
|
31
|
+
attr_reader :label
|
32
|
+
|
33
|
+
# Measured time in microsecond.
|
34
|
+
# @return [Integer] number of microseconds.
|
35
|
+
attr_reader :microseconds
|
36
|
+
|
37
|
+
# Number of Iterations.
|
38
|
+
# @return [Integer] number of iterations.
|
39
|
+
attr_reader :iterations
|
40
|
+
|
41
|
+
# Iterations per second.
|
42
|
+
# @return [Float] number of iterations per second.
|
43
|
+
attr_reader :ips
|
44
|
+
|
45
|
+
# Standard deviation of iteration per second.
|
46
|
+
# @return [Float] standard deviation of iteration per second.
|
47
|
+
attr_reader :ips_sd
|
48
|
+
|
49
|
+
# Number of Cycles.
|
50
|
+
# @return [Integer] number of cycles.
|
51
|
+
attr_reader :measurement_cycle
|
18
52
|
|
53
|
+
# Control if the total time the job took is reported.
|
54
|
+
# Typically this value is not significant because it's very
|
55
|
+
# close to the expected time, so it's supressed by default.
|
56
|
+
def show_total_time!
|
57
|
+
@show_total_time = true
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return entry's microseconds in seconds.
|
61
|
+
# @return [Float] +@microseconds+ in seconds.
|
19
62
|
def seconds
|
20
63
|
@microseconds.to_f / 1_000_000.0
|
21
64
|
end
|
22
65
|
|
66
|
+
# Return entry's standard deviation of iteration per second in percentage.
|
67
|
+
# @return [Float] +@ips_sd+ in percentage.
|
23
68
|
def stddev_percentage
|
24
69
|
100.0 * (@ips_sd.to_f / @ips.to_f)
|
25
70
|
end
|
26
71
|
|
27
72
|
alias_method :runtime, :seconds
|
28
73
|
|
74
|
+
# Return Entry body text with left padding.
|
75
|
+
# Body text contains information of iteration per second with
|
76
|
+
# percentage of standard deviation, iterations in runtime.
|
77
|
+
# @return [String] Left justified body.
|
29
78
|
def body
|
30
|
-
|
31
|
-
|
79
|
+
case Benchmark::IPS.options[:format]
|
80
|
+
when :human
|
81
|
+
left = "%s (±%4.1f%%) i/s" % [Helpers.scale(ips), stddev_percentage]
|
82
|
+
iters = Helpers.scale(@iterations)
|
83
|
+
|
84
|
+
if @show_total_time
|
85
|
+
left.ljust(20) + (" - %s in %10.6fs" % [iters, runtime])
|
86
|
+
else
|
87
|
+
left.ljust(20) + (" - %s" % iters)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
left = "%10.1f (±%.1f%%) i/s" % [ips, stddev_percentage]
|
91
|
+
|
92
|
+
if @show_total_time
|
93
|
+
left.ljust(20) + (" - %10d in %10.6fs" % [@iterations, runtime])
|
94
|
+
else
|
95
|
+
left.ljust(20) + (" - %10d" % @iterations)
|
96
|
+
end
|
97
|
+
end
|
32
98
|
end
|
33
99
|
|
100
|
+
# Return header with padding if +@label+ is < length of 20.
|
101
|
+
# @return [String] Right justified header (+@label+).
|
34
102
|
def header
|
35
103
|
@label.rjust(20)
|
36
104
|
end
|
37
105
|
|
106
|
+
# Return string repesentation of Entry object.
|
107
|
+
# @return [String] Header and body.
|
38
108
|
def to_s
|
39
109
|
"#{header} #{body}"
|
40
110
|
end
|
41
111
|
|
112
|
+
# Print entry to current standard output ($stdout).
|
42
113
|
def display
|
43
114
|
$stdout.puts to_s
|
44
115
|
end
|
45
|
-
end
|
116
|
+
end # End of Entry
|
117
|
+
|
118
|
+
# class Report
|
46
119
|
|
120
|
+
# Entry to represent each benchamarked code in Report.
|
121
|
+
# @return [Array<Entry>] Entries in Report.
|
47
122
|
attr_reader :entries
|
48
123
|
|
124
|
+
# Instantiate the Report.
|
49
125
|
def initialize
|
50
126
|
@entries = []
|
51
127
|
end
|
52
128
|
|
129
|
+
# Add entry to report.
|
130
|
+
# @param label [String] Entry label.
|
131
|
+
# @param microseconds [Integer] Measured time in microsecond.
|
132
|
+
# @param iters [Integer] Iterations.
|
133
|
+
# @param ips [Float] Average Iterations per second.
|
134
|
+
# @param ips_sd [Float] Standard deviation of iterations per second.
|
135
|
+
# @param measurement_cycle [Integer] Number of cycles.
|
136
|
+
# @return [Entry] Last added entry.
|
53
137
|
def add_entry label, microseconds, iters, ips, ips_sd, measurement_cycle
|
54
138
|
@entries << Entry.new(label, microseconds, iters, ips, ips_sd, measurement_cycle)
|
55
139
|
@entries.last
|
56
140
|
end
|
57
141
|
|
142
|
+
# Run comparison of entries.
|
58
143
|
def run_comparison
|
59
144
|
Benchmark.compare(*@entries)
|
60
145
|
end
|
61
|
-
|
62
146
|
end
|
63
147
|
end
|
64
148
|
end
|
data/lib/benchmark/timing.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
module Benchmark
|
2
|
+
# Perform caclulations on Timing results.
|
2
3
|
module Timing
|
4
|
+
|
5
|
+
# Calculate (arithmetic) mean of given samples.
|
6
|
+
# @param [Array] samples Samples to calculate mean.
|
7
|
+
# @return [Float] Mean of given samples.
|
3
8
|
def self.mean(samples)
|
4
9
|
sum = samples.inject(0) { |acc, i| acc + i }
|
5
10
|
sum / samples.size
|
6
11
|
end
|
7
12
|
|
13
|
+
# Calculate variance of given samples.
|
14
|
+
# @param [Float] m Optional mean (Expected value).
|
15
|
+
# @return [Float] Variance of given samples.
|
8
16
|
def self.variance(samples, m=nil)
|
9
17
|
m ||= mean(samples)
|
10
18
|
|
@@ -13,10 +21,17 @@ module Benchmark
|
|
13
21
|
total / samples.size
|
14
22
|
end
|
15
23
|
|
24
|
+
# Calculate standard deviation of given samples.
|
25
|
+
# @param [Array] samples Samples to calculate standard deviation.
|
26
|
+
# @param [Float] m Optional mean (Expected value).
|
27
|
+
# @return [Float] standard deviation of given samples.
|
16
28
|
def self.stddev(samples, m=nil)
|
17
29
|
Math.sqrt variance(samples, m)
|
18
30
|
end
|
19
31
|
|
32
|
+
# Resample mean of given samples.
|
33
|
+
# @param [Integer] resample_times Resample times, defaults to 100.
|
34
|
+
# @return [Array] Resampled samples.
|
20
35
|
def self.resample_mean(samples, resample_times=100)
|
21
36
|
resamples = []
|
22
37
|
|
@@ -28,6 +43,7 @@ module Benchmark
|
|
28
43
|
resamples
|
29
44
|
end
|
30
45
|
|
46
|
+
# Recycle unsed objects by starting Garbage Collector.
|
31
47
|
def self.clean_env
|
32
48
|
# rbx
|
33
49
|
if GC.respond_to? :run
|
data/test/test_benchmark_ips.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: benchmark-ips
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '5.
|
19
|
+
version: '5.4'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
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.4'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rdoc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,15 +44,15 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
47
|
+
version: '3.13'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
55
|
-
description: A iterations per second enhancement to Benchmark
|
54
|
+
version: '3.13'
|
55
|
+
description: A iterations per second enhancement to Benchmark.
|
56
56
|
email:
|
57
57
|
- evan@phx.io
|
58
58
|
executables: []
|
@@ -69,13 +69,12 @@ files:
|
|
69
69
|
- README.md
|
70
70
|
- Rakefile
|
71
71
|
- lib/benchmark/compare.rb
|
72
|
-
- lib/benchmark/helpers.rb
|
73
72
|
- lib/benchmark/ips.rb
|
74
73
|
- lib/benchmark/ips/job.rb
|
75
74
|
- lib/benchmark/ips/report.rb
|
76
75
|
- lib/benchmark/timing.rb
|
77
76
|
- test/test_benchmark_ips.rb
|
78
|
-
homepage:
|
77
|
+
homepage: https://github.com/evanphx/benchmark-ips
|
79
78
|
licenses:
|
80
79
|
- MIT
|
81
80
|
metadata: {}
|
@@ -100,6 +99,6 @@ rubyforge_project:
|
|
100
99
|
rubygems_version: 2.2.2
|
101
100
|
signing_key:
|
102
101
|
specification_version: 4
|
103
|
-
summary: A iterations per second enhancement to Benchmark
|
102
|
+
summary: A iterations per second enhancement to Benchmark.
|
104
103
|
test_files:
|
105
104
|
- test/test_benchmark_ips.rb
|
data/lib/benchmark/helpers.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module Benchmark
|
2
|
-
module Helpers
|
3
|
-
|
4
|
-
def fixnum_max
|
5
|
-
if Object.const_defined?(:RUBY_ENGINE)
|
6
|
-
case RUBY_ENGINE
|
7
|
-
when "ruby"
|
8
|
-
2 ** (wordsize - 2) - 1
|
9
|
-
when "rbx"
|
10
|
-
Fixnum::MAX
|
11
|
-
when "jruby"
|
12
|
-
9223372036854775807
|
13
|
-
else
|
14
|
-
raise "Maximum Fixnum size now known yet for #{RUBY_ENGINE}"
|
15
|
-
end
|
16
|
-
else
|
17
|
-
2 ** (wordsize - 2) - 1
|
18
|
-
end
|
19
|
-
end
|
20
|
-
module_function :fixnum_max
|
21
|
-
|
22
|
-
def fixnum_min
|
23
|
-
if Object.const_defined?(:RUBY_ENGINE)
|
24
|
-
case RUBY_ENGINE
|
25
|
-
when "ruby"
|
26
|
-
- 2 ** (wordsize - 2)
|
27
|
-
when "rbx"
|
28
|
-
Fixnum::MIN
|
29
|
-
when "jruby"
|
30
|
-
-9223372036854775808
|
31
|
-
else
|
32
|
-
raise "Minimum Fixnum size now known yet for #{RUBY_ENGINE}"
|
33
|
-
end
|
34
|
-
else
|
35
|
-
- 2 ** (wordsize - 2)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
module_function :fixnum_min
|
39
|
-
|
40
|
-
def wordsize
|
41
|
-
8 * 1.size
|
42
|
-
end
|
43
|
-
module_function :wordsize
|
44
|
-
|
45
|
-
end
|
46
|
-
end
|