benchmark-inputs 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -3
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -1
- data/README.md +35 -25
- data/Rakefile +0 -13
- data/benchmark-inputs.gemspec +12 -11
- data/lib/benchmark/inputs.rb +35 -59
- data/lib/benchmark/inputs/version.rb +1 -1
- metadata +10 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ace507d5a3b56178d74bafca22757751db45fc0aa35fcf11688fcfd0ab6a5359
|
4
|
+
data.tar.gz: e25a1f06aa67210490fb418dd96a00deb3014cd6b1d72f291afda0ff62b271b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 489255b3e502c218342f416b98d1c3ab3281088dafb62156fa2782529619a1d35b8cd13a38c7075e816a9869ce6bc39dec505c46eec5f2958c2c0351eeb494a1
|
7
|
+
data.tar.gz: f7fa7a6f0107022bb1e1b56830eb414d0dfb60a95f1986d7629ebfaae4dc6d8f376b12e7aace21f117034f461e1169be235fe876c902e29fc4e5111f5ccfaa0d
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# benchmark-inputs
|
1
|
+
# benchmark-inputs [![Build Status](https://travis-ci.org/jonathanhefner/benchmark-inputs.svg?branch=master)](https://travis-ci.org/jonathanhefner/benchmark-inputs)
|
2
2
|
|
3
3
|
Input-focused benchmarking for Ruby. Given one or more blocks and an
|
4
4
|
array of inputs to yield to each of them, benchmark-inputs will measure
|
@@ -18,8 +18,8 @@ require "benchmark/ips" ### USING benchmark-ips (NOT benchmark-inputs)
|
|
18
18
|
|
19
19
|
STRINGS = ["abc", "aaa", "xyz", ""]
|
20
20
|
Benchmark.ips do |job|
|
21
|
-
job.report("String#tr"){ STRINGS.each{|
|
22
|
-
job.report("String#gsub"){ STRINGS.each{|
|
21
|
+
job.report("String#tr"){ STRINGS.each{|string| string.tr("a", "A") } }
|
22
|
+
job.report("String#gsub"){ STRINGS.each{|string| string.gsub(/a/, "A") } }
|
23
23
|
job.compare!
|
24
24
|
end
|
25
25
|
```
|
@@ -33,33 +33,36 @@ each value individually, but that is more verbose and more error-prone:
|
|
33
33
|
```ruby
|
34
34
|
require "benchmark/ips" ### USING benchmark-ips (NOT benchmark-inputs)
|
35
35
|
|
36
|
-
|
36
|
+
string1, string2, string3, string4 = ["abc", "aaa", "xyz", ""]
|
37
37
|
Benchmark.ips do |job|
|
38
38
|
job.report("String#tr") do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
string1.tr("a", "A")
|
40
|
+
string2.tr("a", "A")
|
41
|
+
string3.tr("a", "A")
|
42
|
+
string4.tr("a", "A")
|
43
43
|
end
|
44
44
|
job.report("String#gsub") do
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
string1.gsub(/a/, "A")
|
46
|
+
string2.gsub(/a/, "A")
|
47
|
+
string3.gsub(/a/, "A")
|
48
|
+
string4.gsub(/a/, "A")
|
49
49
|
end
|
50
50
|
job.compare!
|
51
51
|
end
|
52
52
|
```
|
53
53
|
|
54
|
+
|
55
|
+
## Usage
|
56
|
+
|
54
57
|
*Enter benchmark-inputs*. Here is how the same benchmark looks using
|
55
|
-
this gem:
|
58
|
+
this gem:
|
56
59
|
|
57
60
|
```ruby
|
58
61
|
require "benchmark/inputs" ### USING benchmark-inputs
|
59
62
|
|
60
63
|
Benchmark.inputs(["abc", "aaa", "xyz", ""]) do |job|
|
61
|
-
job.report("String#tr"){|
|
62
|
-
job.report("String#gsub"){|
|
64
|
+
job.report("String#tr"){|string| string.tr("a", "A") }
|
65
|
+
job.report("String#gsub"){|string| string.gsub(/a/, "A") }
|
63
66
|
job.compare!
|
64
67
|
end
|
65
68
|
```
|
@@ -93,8 +96,8 @@ behind the scenes. To enable this, use the `dup_inputs` option:
|
|
93
96
|
require "benchmark/inputs"
|
94
97
|
|
95
98
|
Benchmark.inputs(["abc", "aaa", "xyz", ""], dup_inputs: true) do |job|
|
96
|
-
job.report("String#tr!"){|
|
97
|
-
job.report("String#gsub!"){|
|
99
|
+
job.report("String#tr!"){|string| string.tr!("a", "A") }
|
100
|
+
job.report("String#gsub!"){|string| string.gsub!(/a/, "A") }
|
98
101
|
job.compare!
|
99
102
|
end
|
100
103
|
```
|
@@ -112,13 +115,18 @@ Comparison:
|
|
112
115
|
String#gsub!: 281588.6 i/s - 6.37x slower
|
113
116
|
```
|
114
117
|
|
115
|
-
|
118
|
+
The above shows a slightly larger performance gap than the previous
|
116
119
|
benchmark. This makes sense because the overhead of allocating new
|
117
120
|
strings -- previously via a non-bang method, but now via `dup` -- is now
|
118
121
|
excluded from the timings. Thus, the speed of `tr!` relative to `gsub!`
|
119
122
|
is further emphasized.
|
120
123
|
|
121
124
|
|
125
|
+
## API
|
126
|
+
|
127
|
+
See the [API documentation](https://www.rubydoc.info/gems/benchmark-inputs).
|
128
|
+
|
129
|
+
|
122
130
|
## Limitations
|
123
131
|
|
124
132
|
`Benchmark.inputs` generates code based on the array of input values it
|
@@ -126,26 +134,28 @@ is given. Each input value becomes a local variable. While there is
|
|
126
134
|
theoretically no limit to the number of local variables that can be
|
127
135
|
generated, more than a few hundred may slow down the benchmark. But,
|
128
136
|
because input values are used to represent different scenarios rather
|
129
|
-
than control the number of invocations, this limitation
|
130
|
-
problem.
|
137
|
+
than control the number of invocations, this limitation should not pose
|
138
|
+
a problem.
|
131
139
|
|
132
140
|
|
133
141
|
## Installation
|
134
142
|
|
143
|
+
Install the [gem](https://rubygems.org/gems/benchmark-inputs):
|
144
|
+
|
135
145
|
```bash
|
136
146
|
$ gem install benchmark-inputs
|
137
147
|
```
|
138
148
|
|
149
|
+
Then require in your benchmark script:
|
139
150
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
[API documentation](http://www.rubydoc.info/gems/benchmark-inputs).
|
151
|
+
```ruby
|
152
|
+
require "benchmark/inputs"
|
153
|
+
```
|
144
154
|
|
145
155
|
|
146
156
|
## License
|
147
157
|
|
148
|
-
[MIT License](
|
158
|
+
[MIT License](LICENSE.txt)
|
149
159
|
|
150
160
|
|
151
161
|
|
data/Rakefile
CHANGED
@@ -1,18 +1,5 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
|
-
require "yard"
|
4
|
-
|
5
|
-
|
6
|
-
desc 'Launch IRB with this gem pre-loaded'
|
7
|
-
task :irb do
|
8
|
-
require "benchmark/inputs"
|
9
|
-
require "irb"
|
10
|
-
ARGV.clear
|
11
|
-
IRB.start
|
12
|
-
end
|
13
|
-
|
14
|
-
YARD::Rake::YardocTask.new(:doc) do |t|
|
15
|
-
end
|
16
3
|
|
17
4
|
Rake::TestTask.new(:test) do |t|
|
18
5
|
t.libs << "test"
|
data/benchmark-inputs.gemspec
CHANGED
@@ -1,25 +1,26 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'benchmark/inputs/version'
|
1
|
+
require_relative "lib/benchmark/inputs/version"
|
5
2
|
|
6
3
|
Gem::Specification.new do |spec|
|
7
4
|
spec.name = "benchmark-inputs"
|
8
5
|
spec.version = Benchmark::Inputs::VERSION
|
9
6
|
spec.authors = ["Jonathan Hefner"]
|
10
|
-
spec.email = ["jonathan
|
7
|
+
spec.email = ["jonathan@hefner.pro"]
|
11
8
|
|
12
9
|
spec.summary = %q{Input-focused benchmarking}
|
13
10
|
spec.homepage = "https://github.com/jonathanhefner/benchmark-inputs"
|
14
11
|
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = ">= 2.2"
|
15
13
|
|
16
|
-
spec.
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
16
|
+
spec.metadata["changelog_uri"] = spec.metadata["source_code_uri"] + "/blob/master/CHANGELOG.md"
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(__dir__) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
17
23
|
spec.bindir = "exe"
|
18
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
25
|
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.12"
|
22
|
-
spec.add_development_dependency "rake", ">= 10.0"
|
23
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
24
|
-
spec.add_development_dependency "yard", "~> 0.9"
|
25
26
|
end
|
data/lib/benchmark/inputs.rb
CHANGED
@@ -2,44 +2,41 @@ require "benchmark/inputs/version"
|
|
2
2
|
|
3
3
|
module Benchmark
|
4
4
|
|
5
|
-
# Initializes a benchmark
|
6
|
-
# job to the given block.
|
5
|
+
# Initializes a benchmark Job, and yields the Job to the given block.
|
7
6
|
#
|
8
7
|
# @example Benchmarking non-destructive operations
|
9
8
|
# Benchmark.inputs(["abc", "aaa", "xyz", ""]) do |job|
|
10
|
-
# job.report("String#tr"){|
|
11
|
-
# job.report("String#gsub"){|
|
9
|
+
# job.report("String#tr"){|string| string.tr("a", "A") }
|
10
|
+
# job.report("String#gsub"){|string| string.gsub(/a/, "A") }
|
12
11
|
# job.compare!
|
13
12
|
# end
|
14
13
|
#
|
15
14
|
# @example Benchmarking destructive operations
|
16
15
|
# Benchmark.inputs(["abc", "aaa", "xyz", ""], dup_inputs: true) do |job|
|
17
|
-
# job.report("String#tr!"){|
|
18
|
-
# job.report("String#gsub!"){|
|
16
|
+
# job.report("String#tr!"){|string| string.tr!("a", "A") }
|
17
|
+
# job.report("String#gsub!"){|string| string.gsub!(/a/, "A") }
|
19
18
|
# job.compare!
|
20
19
|
# end
|
21
20
|
#
|
22
21
|
# @param values [Array]
|
23
|
-
#
|
22
|
+
# Input values to be individually yielded to all {Inputs::Job#report
|
23
|
+
# +report+} blocks
|
24
24
|
# @param options [Hash]
|
25
|
-
# @option options :dup_inputs [Boolean]
|
26
|
-
#
|
27
|
-
# {Inputs::Job#report} block
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# take when
|
33
|
-
#
|
34
|
-
# configures job and runs benchmarks
|
25
|
+
# @option options :dup_inputs [Boolean] (false)
|
26
|
+
# Whether each of +values+ should be +dup+'d before being yielded to
|
27
|
+
# a {Inputs::Job#report +report+} block. This should be set to true
|
28
|
+
# if any +report+ block destructively modifies its input.
|
29
|
+
# @option options :sample_n [Integer] (10)
|
30
|
+
# Number of samples to take when benchmarking
|
31
|
+
# @option options :sample_dt [Integer] (200,000 ns)
|
32
|
+
# Approximate duration of time each sample should take when
|
33
|
+
# benchmarking, in nanoseconds
|
35
34
|
# @yieldparam job [Benchmark::Inputs::Job]
|
36
|
-
# benchmark runner
|
37
35
|
# @return [Benchmark::Inputs::Job]
|
38
|
-
# benchmark runner
|
39
36
|
# @raise [ArgumentError]
|
40
37
|
# if +values+ is empty
|
41
38
|
def self.inputs(values, **options)
|
42
|
-
job = Inputs::Job.new(values, options)
|
39
|
+
job = Inputs::Job.new(values, **options)
|
43
40
|
yield job
|
44
41
|
job
|
45
42
|
end
|
@@ -47,23 +44,14 @@ module Benchmark
|
|
47
44
|
|
48
45
|
module Inputs
|
49
46
|
|
47
|
+
# @!visibility private
|
50
48
|
NS_PER_S = 1_000_000_000
|
49
|
+
# @!visibility private
|
51
50
|
NS_PER_MS = NS_PER_S / 1_000
|
52
51
|
|
53
52
|
class Job
|
54
53
|
|
55
|
-
#
|
56
|
-
# input values to yield to each benchmark action
|
57
|
-
# @param dup_inputs [Boolean]
|
58
|
-
# whether input values will be +dup+-ed before they are passed
|
59
|
-
# to a {report} block
|
60
|
-
# @param sample_n [Integer]
|
61
|
-
# number of samples to take when benchmarking
|
62
|
-
# @param sample_dt [Integer]
|
63
|
-
# approximate duration of time (in nanoseconds) each sample
|
64
|
-
# should take when benchmarking
|
65
|
-
# @raise [ArgumentError]
|
66
|
-
# if +inputs+ is empty
|
54
|
+
# @!visibility private
|
67
55
|
def initialize(inputs, dup_inputs: false, sample_n: 10, sample_dt: NS_PER_MS * 200)
|
68
56
|
raise ArgumentError, "No inputs specified" if inputs.empty?
|
69
57
|
|
@@ -75,16 +63,9 @@ module Benchmark
|
|
75
63
|
def_bench!
|
76
64
|
end
|
77
65
|
|
78
|
-
# Indicates whether input values will be +dup+-ed before they are
|
79
|
-
# passed to a {report} block. Defaults to +false+. This should
|
80
|
-
# be set to +true+ if {report} blocks destructively modify their
|
81
|
-
# arguments.
|
82
|
-
#
|
83
66
|
# @return [Boolean]
|
84
67
|
attr_reader :dup_inputs
|
85
68
|
|
86
|
-
# See {dup_inputs}.
|
87
|
-
#
|
88
69
|
# @param flag [Boolean]
|
89
70
|
# @return [Boolean]
|
90
71
|
def dup_inputs=(flag)
|
@@ -93,14 +74,9 @@ module Benchmark
|
|
93
74
|
@dup_inputs
|
94
75
|
end
|
95
76
|
|
96
|
-
# The number of samples to take when benchmarking. Defaults to 10.
|
97
|
-
#
|
98
77
|
# @return [Integer]
|
99
78
|
attr_accessor :sample_n
|
100
79
|
|
101
|
-
# The approximate duration of time (in nanoseconds) each sample
|
102
|
-
# should take when benchmarking. Defaults to 200,000 nanoseconds.
|
103
|
-
#
|
104
80
|
# @return [Integer]
|
105
81
|
attr_accessor :sample_dt
|
106
82
|
|
@@ -110,18 +86,16 @@ module Benchmark
|
|
110
86
|
# @return [Array<Benchmark::Inputs::Report>]
|
111
87
|
attr_reader :reports
|
112
88
|
|
113
|
-
# Benchmarks the given block using the
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
# {
|
89
|
+
# Benchmarks the given block using each of the Job's input values.
|
90
|
+
# If {dup_inputs} is true, each input value is +dup+'d before
|
91
|
+
# being yielded to the block. Prints the block's estimated speed
|
92
|
+
# (in invocations per second) to +$stdout+, and adds a {Report} to
|
93
|
+
# {reports}.
|
118
94
|
#
|
119
95
|
# @param label [String]
|
120
|
-
#
|
121
|
-
# @yield [input]
|
122
|
-
# action to benchmark
|
96
|
+
# Label for the report
|
123
97
|
# @yieldparam input [Object]
|
124
|
-
#
|
98
|
+
# One of the Job's input values
|
125
99
|
# @return [void]
|
126
100
|
def report(label)
|
127
101
|
# estimate repititions
|
@@ -148,7 +122,7 @@ module Benchmark
|
|
148
122
|
end
|
149
123
|
|
150
124
|
# Prints the relative speeds (from fastest to slowest) of all
|
151
|
-
# {
|
125
|
+
# {reports} to +$stdout+.
|
152
126
|
#
|
153
127
|
# @return [void]
|
154
128
|
def compare!
|
@@ -210,9 +184,11 @@ module Benchmark
|
|
210
184
|
# @return [String]
|
211
185
|
attr_reader :label
|
212
186
|
|
213
|
-
# The ratio of
|
214
|
-
#
|
215
|
-
#
|
187
|
+
# The ratio of the speed from the fastest report compared to the
|
188
|
+
# speed from this report. In other words, the "slower than
|
189
|
+
# fastest by" multiplier for this report. Will be +nil+ if the
|
190
|
+
# absolute difference in speed between the two reports falls
|
191
|
+
# within the combined measurement error.
|
216
192
|
#
|
217
193
|
# This value is set by {Benchmark::Inputs::Job#compare!}.
|
218
194
|
#
|
@@ -243,14 +219,14 @@ module Benchmark
|
|
243
219
|
@stddev = nil
|
244
220
|
end
|
245
221
|
|
246
|
-
# The estimated
|
222
|
+
# The estimated speed for the report, in invocations per second.
|
247
223
|
#
|
248
224
|
# @return [Float]
|
249
225
|
def ips
|
250
226
|
@mean
|
251
227
|
end
|
252
228
|
|
253
|
-
# The
|
229
|
+
# The standard deviation of the estimated speed for the report.
|
254
230
|
#
|
255
231
|
# @return [Float]
|
256
232
|
def stddev
|
metadata
CHANGED
@@ -1,74 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: benchmark-inputs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Hefner
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.12'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.12'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '10.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '10.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '5.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '5.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: yard
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.9'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0.9'
|
11
|
+
date: 2020-09-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
69
13
|
description:
|
70
14
|
email:
|
71
|
-
- jonathan
|
15
|
+
- jonathan@hefner.pro
|
72
16
|
executables: []
|
73
17
|
extensions: []
|
74
18
|
extra_rdoc_files: []
|
@@ -86,7 +30,10 @@ files:
|
|
86
30
|
homepage: https://github.com/jonathanhefner/benchmark-inputs
|
87
31
|
licenses:
|
88
32
|
- MIT
|
89
|
-
metadata:
|
33
|
+
metadata:
|
34
|
+
homepage_uri: https://github.com/jonathanhefner/benchmark-inputs
|
35
|
+
source_code_uri: https://github.com/jonathanhefner/benchmark-inputs
|
36
|
+
changelog_uri: https://github.com/jonathanhefner/benchmark-inputs/blob/master/CHANGELOG.md
|
90
37
|
post_install_message:
|
91
38
|
rdoc_options: []
|
92
39
|
require_paths:
|
@@ -95,14 +42,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
42
|
requirements:
|
96
43
|
- - ">="
|
97
44
|
- !ruby/object:Gem::Version
|
98
|
-
version: '
|
45
|
+
version: '2.2'
|
99
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
47
|
requirements:
|
101
48
|
- - ">="
|
102
49
|
- !ruby/object:Gem::Version
|
103
50
|
version: '0'
|
104
51
|
requirements: []
|
105
|
-
rubygems_version: 3.
|
52
|
+
rubygems_version: 3.1.2
|
106
53
|
signing_key:
|
107
54
|
specification_version: 4
|
108
55
|
summary: Input-focused benchmarking
|