benchmark-perf 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +21 -5
- data/README.md +48 -11
- data/benchmark-perf.gemspec +8 -4
- data/lib/benchmark-perf.rb +1 -3
- data/lib/benchmark/perf.rb +41 -13
- data/lib/benchmark/perf/execution_time.rb +20 -34
- data/lib/benchmark/perf/iteration.rb +22 -17
- data/lib/benchmark/perf/version.rb +2 -2
- data/spec/unit/assertions_spec.rb +3 -3
- data/spec/unit/execution_time_spec.rb +16 -15
- data/spec/unit/iteration_spec.rb +5 -7
- data/tasks/console.rake +11 -0
- metadata +26 -22
- data/.gitignore +0 -14
- data/.rspec +0 -2
- data/.travis.yml +0 -28
- data/Gemfile +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d7fe9d604c0acf5ef3342b1bb0f7dc4e25c4842be28f2dcfccfa294afc1c7699
|
4
|
+
data.tar.gz: 9c99fac42b55347306729883c255e7976d7185e94ccf00fdf8985bbcdc40271c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc1775bb46d926fd6c23df11c4c257ead8c5818b05814b34760f1500aa8226ede1e5f46d2be974d2303ba9b2749b58ab75714662ba13485230eaa334ab3d6693
|
7
|
+
data.tar.gz: 81a6b09450fbcd6bb61ac110cef837e163e8635734b59328c6c1ff06d251804e349de88efe03446ea43ceb8ee5960a19bb63d1f16c0a36e494cdedb819c16006
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
-
## [v0.
|
3
|
+
## [v0.3.0] - 2018-09-16
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add a monotonic time measurement
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
* Change to use Ruby >= 2.0.0
|
10
|
+
* Change Iteration to be a module and remove state
|
11
|
+
* Change ExecutionTime to be a module and remove state
|
12
|
+
* Change ExecutionTime#run to accept :warmup, :times
|
13
|
+
* Change ExecutionTime & Iteration to measure using monotonic clock
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
* Fixe ExecutionTime#run to correctly calculate linear range of samples
|
17
|
+
|
18
|
+
## [v0.2.1] - 2016-11-03
|
4
19
|
|
5
20
|
### Changed
|
6
21
|
* Remove rescuing marshalling errors
|
@@ -25,7 +40,8 @@
|
|
25
40
|
|
26
41
|
Initial release
|
27
42
|
|
28
|
-
[v0.
|
29
|
-
[v0.2.
|
30
|
-
[v0.
|
31
|
-
[v0.1.
|
43
|
+
[v0.3.0]: https://github.com/piotrmurach/benchmark-perf/compare/v0.2.1...v0.3.0
|
44
|
+
[v0.2.1]: https://github.com/piotrmurach/benchmark-perf/compare/v0.2.0...v0.2.1
|
45
|
+
[v0.2.0]: https://github.com/piotrmurach/benchmark-perf/compare/v0.1.1...v0.2.0
|
46
|
+
[v0.1.1]: https://github.com/piotrmurach/benchmark-perf/compare/v0.1.0...v0.1.1
|
47
|
+
[v0.1.0]: https://github.com/piotrmurach/benchmark-perf/compare/v0.1.0
|
data/README.md
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
[][gem]
|
4
4
|
[][travis]
|
5
|
+
[][appveyor]
|
5
6
|
[][codeclimate]
|
6
7
|
[][coverage]
|
7
8
|
[][inchpages]
|
8
9
|
|
9
10
|
[gem]: http://badge.fury.io/rb/benchmark-perf
|
10
11
|
[travis]: http://travis-ci.org/piotrmurach/benchmark-perf
|
12
|
+
[appveyor]: https://ci.appveyor.com/project/piotrmurach/benchmark-perf
|
11
13
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/benchmark-perf
|
12
14
|
[coverage]: https://coveralls.io/github/piotrmurach/benchmark-perf?branch=master
|
13
15
|
[inchpages]: http://inch-ci.org/github/piotrmurach/benchmark-perf
|
@@ -32,32 +34,67 @@ Or install it yourself as:
|
|
32
34
|
|
33
35
|
$ gem install benchmark-perf
|
34
36
|
|
35
|
-
##
|
37
|
+
## Contents
|
36
38
|
|
37
|
-
|
39
|
+
* [1. Usage](#1-usage)
|
40
|
+
* [2. API](#2-api)
|
41
|
+
* [2.1 Execution time](#21-execution-time)
|
42
|
+
* [2.2 Iterations](#22-iterations)
|
43
|
+
|
44
|
+
## 1. Usage
|
45
|
+
|
46
|
+
To see how long it takes to execute a piece of code:
|
38
47
|
|
39
48
|
```ruby
|
40
|
-
|
41
|
-
mean, stddev = bench.run { ... }
|
49
|
+
mean, stddev = Benchmark::Perf::ExecutionTime.run { ... }
|
42
50
|
```
|
43
51
|
|
44
|
-
|
52
|
+
or to see how many iterations per second a piece of code can achieve:
|
45
53
|
|
46
54
|
```ruby
|
47
|
-
|
55
|
+
mean, stddev, iter, elapsed_time = Benchmark::Perf::Iteration.run { ... }
|
48
56
|
```
|
49
57
|
|
50
|
-
|
58
|
+
## 2. API
|
59
|
+
|
60
|
+
### 2.1 Execution time
|
61
|
+
|
62
|
+
By default `30` samples are taken, and `1` sample for the warmup phase. If you need to change number of measurement samples use `:times`:
|
51
63
|
|
52
64
|
```ruby
|
53
|
-
|
65
|
+
mean, std_dev = Benchmark::Perf::ExecutionTime.run(times: 10) { ... }
|
54
66
|
```
|
55
67
|
|
68
|
+
And to change number of warmup cycles use `:warmup` keyword like so:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
Benchmark::Perf::ExecutionTime.run(warmup: 2) { ... }
|
72
|
+
```
|
73
|
+
|
74
|
+
If you're interested in having debug output to see exact measurements for each iteration specify stream with `:io`:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
Benchmark::Perf::ExecutionTime.run(io: $stdout) { ... }
|
78
|
+
```
|
79
|
+
|
80
|
+
### 2.2 Iterations
|
81
|
+
|
56
82
|
In order to check how many iterations per second a given code takes do:
|
57
83
|
|
58
84
|
```ruby
|
59
|
-
|
60
|
-
|
85
|
+
mean, stddev, iter, elapsed_time = Benchmark::Perf::Iteration.run { ... }
|
86
|
+
```
|
87
|
+
|
88
|
+
By default `1` second is spent warming up Ruby VM, you change this passing `:warmup` :
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
Benchmark::Perf::Itertion.run(warmup: 1.45) { ... } # 1.45 second
|
92
|
+
```
|
93
|
+
|
94
|
+
The measurements as sampled for `2` seconds, you can change this value to increase precision using `:time`:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
Benchmark::Perf::Iteration.run(time: 3.5) { ... } # 3.5 seconds
|
61
98
|
```
|
62
99
|
|
63
100
|
## Contributing
|
@@ -70,4 +107,4 @@ mean, stddev, iter, elapsed_time = bench.run { ... }
|
|
70
107
|
|
71
108
|
## Copyright
|
72
109
|
|
73
|
-
Copyright (c) 2016 Piotr Murach. See LICENSE for further details.
|
110
|
+
Copyright (c) 2016-2018 Piotr Murach. See LICENSE for further details.
|
data/benchmark-perf.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'benchmark/perf/version'
|
@@ -13,11 +12,16 @@ Gem::Specification.new do |spec|
|
|
13
12
|
spec.homepage = ""
|
14
13
|
spec.license = "MIT"
|
15
14
|
|
16
|
-
spec.files =
|
15
|
+
spec.files = Dir['{lib,spec}/**/*.rb']
|
16
|
+
spec.files += Dir['tasks/*', 'benchmark-perf.gemspec']
|
17
|
+
spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^spec/})
|
19
20
|
spec.require_paths = ["lib"]
|
20
21
|
|
21
|
-
spec.
|
22
|
-
|
22
|
+
spec.required_ruby_version = '>= 2.0.0'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
27
|
end
|
data/lib/benchmark-perf.rb
CHANGED
data/lib/benchmark/perf.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'benchmark'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
require_relative 'perf/execution_time'
|
6
|
+
require_relative 'perf/iteration'
|
7
|
+
require_relative 'perf/version'
|
8
8
|
|
9
9
|
module Benchmark
|
10
10
|
module Perf
|
@@ -16,10 +16,11 @@ module Benchmark
|
|
16
16
|
# the average of given measurements
|
17
17
|
#
|
18
18
|
# @api public
|
19
|
-
def
|
19
|
+
def average(measurements)
|
20
20
|
return 0 if measurements.empty?
|
21
21
|
measurements.reduce(&:+).to_f / measurements.size
|
22
22
|
end
|
23
|
+
module_function :average
|
23
24
|
|
24
25
|
# Calculate variance of measurements
|
25
26
|
#
|
@@ -28,7 +29,7 @@ module Benchmark
|
|
28
29
|
# @return [Float]
|
29
30
|
#
|
30
31
|
# @api public
|
31
|
-
def
|
32
|
+
def variance(measurements)
|
32
33
|
return 0 if measurements.empty?
|
33
34
|
avg = average(measurements)
|
34
35
|
total = measurements.reduce(0) do |sum, x|
|
@@ -36,16 +37,18 @@ module Benchmark
|
|
36
37
|
end
|
37
38
|
total.to_f / measurements.size
|
38
39
|
end
|
40
|
+
module_function :variance
|
39
41
|
|
40
42
|
# Calculate standard deviation
|
41
43
|
#
|
42
44
|
# @param [Array[Float]] measurements
|
43
45
|
#
|
44
46
|
# @api public
|
45
|
-
def
|
47
|
+
def std_dev(measurements)
|
46
48
|
return 0 if measurements.empty?
|
47
49
|
Math.sqrt(variance(measurements))
|
48
50
|
end
|
51
|
+
module_function :std_dev
|
49
52
|
|
50
53
|
# Run given work and gather time statistics
|
51
54
|
#
|
@@ -54,11 +57,11 @@ module Benchmark
|
|
54
57
|
# @return [Boolean]
|
55
58
|
#
|
56
59
|
# @api public
|
57
|
-
def
|
58
|
-
|
59
|
-
actual, _ = bench.run(&work)
|
60
|
+
def assert_perform_under(threshold, options = {}, &work)
|
61
|
+
actual, _ = ExecutionTime.run(options, &work)
|
60
62
|
actual <= threshold
|
61
63
|
end
|
64
|
+
module_function :assert_perform_under
|
62
65
|
|
63
66
|
# Assert work is performed within expected iterations per second
|
64
67
|
#
|
@@ -67,10 +70,35 @@ module Benchmark
|
|
67
70
|
# @return [Boolean]
|
68
71
|
#
|
69
72
|
# @api public
|
70
|
-
def
|
71
|
-
|
72
|
-
mean, stddev, _ = bench.run(&work)
|
73
|
+
def assert_perform_ips(iterations, options = {}, &work)
|
74
|
+
mean, stddev, _ = Iteration.run(options, &work)
|
73
75
|
iterations <= (mean + 3 * stddev)
|
74
76
|
end
|
77
|
+
module_function :assert_perform_ips
|
78
|
+
|
79
|
+
if defined?(Process::CLOCK_MONOTONIC)
|
80
|
+
# Object representing current time
|
81
|
+
def time_now
|
82
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
83
|
+
end
|
84
|
+
module_function :time_now
|
85
|
+
else
|
86
|
+
# Object represeting current time
|
87
|
+
def time_now
|
88
|
+
Time.now
|
89
|
+
end
|
90
|
+
module_function :time_now
|
91
|
+
end
|
92
|
+
|
93
|
+
# Measure time elapsed with a monotonic clock
|
94
|
+
#
|
95
|
+
# @public
|
96
|
+
def clock_time
|
97
|
+
before = time_now
|
98
|
+
yield
|
99
|
+
after = time_now
|
100
|
+
after - before
|
101
|
+
end
|
102
|
+
module_function :clock_time
|
75
103
|
end # Perf
|
76
104
|
end # Benchmark
|
@@ -1,37 +1,18 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Benchmark
|
4
4
|
module Perf
|
5
5
|
# Measure length of time the work could take on average
|
6
6
|
#
|
7
7
|
# @api public
|
8
|
-
|
9
|
-
attr_reader :io
|
10
|
-
|
11
|
-
# Initialize execution time
|
12
|
-
#
|
13
|
-
# @param [Hash] options
|
14
|
-
#
|
15
|
-
# @param options :warmup
|
16
|
-
# the number of cycles for warmup, default 1
|
17
|
-
#
|
18
|
-
# @api public
|
19
|
-
def initialize(options = {})
|
20
|
-
@io = options.fetch(:io) { nil }
|
21
|
-
@samples = options.fetch(:samples) { 30 }
|
22
|
-
@warmup = options.fetch(:warmup) { 1 }
|
23
|
-
end
|
24
|
-
|
8
|
+
module ExecutionTime
|
25
9
|
# Set of ranges in linear progression
|
26
10
|
#
|
27
|
-
# @api
|
11
|
+
# @api public
|
28
12
|
def linear_range(min, max, step = 1)
|
29
13
|
(min..max).step(step).to_a
|
30
14
|
end
|
31
|
-
|
32
|
-
def bench_range
|
33
|
-
linear_range(1, @samples)
|
34
|
-
end
|
15
|
+
module_function :linear_range
|
35
16
|
|
36
17
|
# Isolate run in subprocess
|
37
18
|
#
|
@@ -42,7 +23,7 @@ module Benchmark
|
|
42
23
|
# the elapsed time of the measurement
|
43
24
|
#
|
44
25
|
# @api private
|
45
|
-
def run_in_subprocess
|
26
|
+
def run_in_subprocess(io: nil)
|
46
27
|
return yield unless Process.respond_to?(:fork)
|
47
28
|
|
48
29
|
reader, writer = IO.pipe
|
@@ -70,18 +51,23 @@ module Benchmark
|
|
70
51
|
raise data if data.is_a?(Exception)
|
71
52
|
data
|
72
53
|
end
|
54
|
+
module_function :run_in_subprocess
|
73
55
|
|
74
56
|
# Run warmup measurement
|
75
57
|
#
|
58
|
+
# @param [Numeric] warmup
|
59
|
+
# the warmup time
|
60
|
+
#
|
76
61
|
# @api private
|
77
|
-
def run_warmup(&work)
|
62
|
+
def run_warmup(warmup: 1, &work)
|
78
63
|
GC.start
|
79
|
-
|
64
|
+
warmup.times do
|
80
65
|
run_in_subprocess do
|
81
|
-
|
66
|
+
Perf.clock_time(&work)
|
82
67
|
end
|
83
68
|
end
|
84
69
|
end
|
70
|
+
module_function :run_warmup
|
85
71
|
|
86
72
|
# Perform work x times
|
87
73
|
#
|
@@ -89,28 +75,28 @@ module Benchmark
|
|
89
75
|
# how many times sample the code measuremenets
|
90
76
|
#
|
91
77
|
# @example
|
92
|
-
#
|
93
|
-
# iteration.run(10) { ... }
|
78
|
+
# ExecutionTime.run(times: 10) { ... }
|
94
79
|
#
|
95
80
|
# @return [Array[Float, Float]]
|
96
81
|
# average and standard deviation
|
97
82
|
#
|
98
83
|
# @api public
|
99
|
-
def run(times
|
100
|
-
range =
|
84
|
+
def run(times: 30, io: nil, warmup: 1, &work)
|
85
|
+
range = linear_range(1, times - 1)
|
101
86
|
measurements = []
|
102
|
-
run_warmup(&work)
|
87
|
+
run_warmup(warmup: warmup, &work)
|
103
88
|
|
104
89
|
range.each do
|
105
90
|
GC.start
|
106
|
-
measurements << run_in_subprocess do
|
107
|
-
|
91
|
+
measurements << run_in_subprocess(io: io) do
|
92
|
+
Perf.clock_time(&work)
|
108
93
|
end
|
109
94
|
end
|
110
95
|
io.puts if io
|
111
96
|
|
112
97
|
[Perf.average(measurements), Perf.std_dev(measurements)]
|
113
98
|
end
|
99
|
+
module_function :run
|
114
100
|
end # ExecutionTime
|
115
101
|
end # Perf
|
116
102
|
end # Benchmark
|
@@ -1,19 +1,14 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Benchmark
|
4
4
|
module Perf
|
5
5
|
# Measure number of iterations a work could take in a second
|
6
6
|
#
|
7
7
|
# @api private
|
8
|
-
|
8
|
+
module Iteration
|
9
9
|
MICROSECONDS_PER_SECOND = 1_000_000
|
10
10
|
MICROSECONDS_PER_100MS = 100_000
|
11
11
|
|
12
|
-
def initialize(options = {})
|
13
|
-
@time = options.fetch(:time) { 2 } # Default 2 seconds for measurement
|
14
|
-
@warmup = options.fetch(:warmup) { 1 }
|
15
|
-
end
|
16
|
-
|
17
12
|
# Call work by given times
|
18
13
|
#
|
19
14
|
# @param [Integer] times
|
@@ -30,6 +25,7 @@ module Benchmark
|
|
30
25
|
i += 1
|
31
26
|
end
|
32
27
|
end
|
28
|
+
module_function :call_times
|
33
29
|
|
34
30
|
# Calcualte the number of cycles needed for 100ms
|
35
31
|
#
|
@@ -45,17 +41,21 @@ module Benchmark
|
|
45
41
|
cycles = (iterations * (MICROSECONDS_PER_100MS / elapsed_time)).to_i
|
46
42
|
cycles <= 0 ? 1 : cycles
|
47
43
|
end
|
44
|
+
module_function :cycles_per_100ms
|
48
45
|
|
49
46
|
# Warmup run
|
50
47
|
#
|
48
|
+
# @param [Numeric] warmup
|
49
|
+
# the number of seconds for warmup
|
50
|
+
#
|
51
51
|
# @api private
|
52
|
-
def run_warmup(&work)
|
52
|
+
def run_warmup(warmup: 1, &work)
|
53
53
|
GC.start
|
54
|
-
target =
|
54
|
+
target = Perf.time_now + warmup
|
55
55
|
iter = 0
|
56
56
|
|
57
|
-
elapsed_time =
|
58
|
-
while
|
57
|
+
elapsed_time = Perf.clock_time do
|
58
|
+
while Perf.time_now < target
|
59
59
|
call_times(1, &work)
|
60
60
|
iter += 1
|
61
61
|
end
|
@@ -64,23 +64,27 @@ module Benchmark
|
|
64
64
|
elapsed_time *= MICROSECONDS_PER_SECOND
|
65
65
|
cycles_per_100ms(iter, elapsed_time)
|
66
66
|
end
|
67
|
+
module_function :run_warmup
|
67
68
|
|
68
69
|
# Run measurements
|
69
70
|
#
|
71
|
+
# @param [Numeric] time
|
72
|
+
# the time to run measurements for
|
73
|
+
#
|
70
74
|
# @api public
|
71
|
-
def run(&work)
|
72
|
-
target = Time.now +
|
75
|
+
def run(time: 2, warmup: 1, &work)
|
76
|
+
target = Time.now + time
|
73
77
|
iter = 0
|
74
78
|
measurements = []
|
75
|
-
cycles = run_warmup(&work)
|
79
|
+
cycles = run_warmup(warmup: warmup, &work)
|
76
80
|
|
77
81
|
GC.start
|
78
82
|
|
79
83
|
while Time.now < target
|
80
|
-
|
81
|
-
next if
|
84
|
+
bench_time = Perf.clock_time { call_times(cycles, &work) }
|
85
|
+
next if bench_time <= 0.0 # Iteration took no time
|
82
86
|
iter += cycles
|
83
|
-
measurements <<
|
87
|
+
measurements << bench_time * MICROSECONDS_PER_SECOND
|
84
88
|
end
|
85
89
|
|
86
90
|
ips = measurements.map do |time_ms|
|
@@ -92,6 +96,7 @@ module Benchmark
|
|
92
96
|
|
93
97
|
[Perf.average(ips).round, Perf.std_dev(ips).round, iter, elapsed_time]
|
94
98
|
end
|
99
|
+
module_function :run
|
95
100
|
end # Iteration
|
96
101
|
end # Perf
|
97
102
|
end # Benchmark
|
@@ -1,15 +1,15 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal
|
2
2
|
|
3
3
|
RSpec.describe Benchmark::Perf, 'assertions' do
|
4
4
|
it "passes asertion by performing under threshold" do
|
5
5
|
bench = Benchmark::Perf
|
6
|
-
assertion = bench.assert_perform_under(0.01,
|
6
|
+
assertion = bench.assert_perform_under(0.01, times: 2) { 'x' * 1_024 }
|
7
7
|
expect(assertion).to eq(true)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "passes asertion by performing 10K ips" do
|
11
11
|
bench = Benchmark::Perf
|
12
|
-
assertion = bench.assert_perform_ips(10_000) { 'x' * 1_024 }
|
12
|
+
assertion = bench.assert_perform_ips(10_000, warmup: 1.3) { 'x' * 1_024 }
|
13
13
|
expect(assertion).to eq(true)
|
14
14
|
end
|
15
15
|
end
|
@@ -1,44 +1,45 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Benchmark::Perf::ExecutionTime do
|
4
4
|
it "provides linear range" do
|
5
|
-
|
6
|
-
expect(bench.linear_range(0, 3)).to eq([0,1,2,3])
|
5
|
+
expect(described_class.linear_range(0, 3)).to eq([0,1,2,3])
|
7
6
|
end
|
8
7
|
|
9
8
|
it "provides default benchmark range" do
|
10
|
-
|
11
|
-
|
9
|
+
allow(described_class).to receive(:run_in_subprocess).and_return(0.1)
|
10
|
+
described_class.run { 'x' * 1024 }
|
11
|
+
expect(described_class).to have_received(:run_in_subprocess).exactly(30).times
|
12
|
+
end
|
13
|
+
|
14
|
+
it "accepts custom number of samples" do
|
15
|
+
allow(described_class).to receive(:run_in_subprocess).and_return(0.1)
|
16
|
+
described_class.run(times: 12) { 'x' * 1024 }
|
17
|
+
expect(described_class).to have_received(:run_in_subprocess).exactly(12).times
|
12
18
|
end
|
13
19
|
|
14
20
|
it "provides measurements for 30 samples by default" do
|
15
|
-
|
16
|
-
sample = bench.run { 'x' * 1024 }
|
21
|
+
sample = described_class.run { 'x' * 1024 }
|
17
22
|
expect(sample).to all(be < 0.01)
|
18
23
|
end
|
19
24
|
|
20
25
|
it "doesn't benchmark raised exception" do
|
21
|
-
bench = described_class.new
|
22
26
|
expect {
|
23
|
-
|
27
|
+
described_class.run { raise 'boo' }
|
24
28
|
}.to raise_error(StandardError)
|
25
29
|
end
|
26
30
|
|
27
31
|
it "measures complex object" do
|
28
|
-
|
29
|
-
sample = bench.run { {foo: Object.new, bar: :piotr} }
|
32
|
+
sample = described_class.run { {foo: Object.new, bar: :piotr} }
|
30
33
|
expect(sample).to all(be < 0.01)
|
31
34
|
end
|
32
35
|
|
33
36
|
it "executes code to warmup ruby vm" do
|
34
|
-
|
35
|
-
sample = bench.run_warmup { 'x' * 1_000_000 }
|
37
|
+
sample = described_class.run_warmup { 'x' * 1_000_000 }
|
36
38
|
expect(sample).to eq(1)
|
37
39
|
end
|
38
40
|
|
39
41
|
it "measures work performance for 10 samples" do
|
40
|
-
|
41
|
-
sample = bench.run(10) { 'x' * 1_000_000 }
|
42
|
+
sample = described_class.run(times: 10) { 'x' * 1_000_000 }
|
42
43
|
expect(sample.size).to eq(2)
|
43
44
|
expect(sample).to all(be < 0.01)
|
44
45
|
end
|
data/spec/unit/iteration_spec.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Benchmark::Perf::Iteration do
|
4
4
|
it "defines cycles per 100 microseconds" do
|
5
|
-
|
6
|
-
sample = bench.run_warmup { 'x' * 1_000_000 }
|
5
|
+
sample = described_class.run_warmup { 'x' * 1_000_000 }
|
7
6
|
expect(sample).to be > 25
|
8
7
|
end
|
9
8
|
|
10
9
|
it "measures 10K iterations per second" do
|
11
|
-
|
12
|
-
|
10
|
+
sample = described_class.run { 'x' * 1_000_000 }
|
11
|
+
|
13
12
|
expect(sample.size).to eq(4)
|
14
13
|
expect(sample[0]).to be > 250
|
15
14
|
expect(sample[1]).to be > 5
|
@@ -17,9 +16,8 @@ RSpec.describe Benchmark::Perf::Iteration do
|
|
17
16
|
end
|
18
17
|
|
19
18
|
it "does't measure broken code" do
|
20
|
-
bench = described_class.new
|
21
19
|
expect {
|
22
|
-
|
20
|
+
described_class.run { raise 'boo' }
|
23
21
|
}.to raise_error(StandardError, /boo/)
|
24
22
|
end
|
25
23
|
end
|
data/tasks/console.rake
ADDED
metadata
CHANGED
@@ -1,49 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: benchmark-perf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '2.0'
|
19
|
+
version: '1.16'
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
28
32
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
31
39
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
40
|
+
version: '3.0'
|
33
41
|
- !ruby/object:Gem::Dependency
|
34
42
|
name: rake
|
35
43
|
requirement: !ruby/object:Gem::Requirement
|
36
44
|
requirements:
|
37
|
-
- - "
|
45
|
+
- - "~>"
|
38
46
|
- !ruby/object:Gem::Version
|
39
|
-
version: '0'
|
47
|
+
version: '10.0'
|
40
48
|
type: :development
|
41
49
|
prerelease: false
|
42
50
|
version_requirements: !ruby/object:Gem::Requirement
|
43
51
|
requirements:
|
44
|
-
- - "
|
52
|
+
- - "~>"
|
45
53
|
- !ruby/object:Gem::Version
|
46
|
-
version: '0'
|
54
|
+
version: '10.0'
|
47
55
|
description: Execution time and iteration performance benchmarking
|
48
56
|
email:
|
49
57
|
- ''
|
@@ -51,11 +59,7 @@ executables: []
|
|
51
59
|
extensions: []
|
52
60
|
extra_rdoc_files: []
|
53
61
|
files:
|
54
|
-
- ".gitignore"
|
55
|
-
- ".rspec"
|
56
|
-
- ".travis.yml"
|
57
62
|
- CHANGELOG.md
|
58
|
-
- Gemfile
|
59
63
|
- LICENSE.txt
|
60
64
|
- README.md
|
61
65
|
- Rakefile
|
@@ -70,6 +74,7 @@ files:
|
|
70
74
|
- spec/unit/assertions_spec.rb
|
71
75
|
- spec/unit/execution_time_spec.rb
|
72
76
|
- spec/unit/iteration_spec.rb
|
77
|
+
- tasks/console.rake
|
73
78
|
- tasks/coverage.rake
|
74
79
|
- tasks/spec.rake
|
75
80
|
homepage: ''
|
@@ -84,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
89
|
requirements:
|
85
90
|
- - ">="
|
86
91
|
- !ruby/object:Gem::Version
|
87
|
-
version:
|
92
|
+
version: 2.0.0
|
88
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
94
|
requirements:
|
90
95
|
- - ">="
|
@@ -92,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
97
|
version: '0'
|
93
98
|
requirements: []
|
94
99
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
100
|
+
rubygems_version: 2.7.3
|
96
101
|
signing_key:
|
97
102
|
specification_version: 4
|
98
103
|
summary: Execution time and iteration performance benchmarking
|
@@ -102,4 +107,3 @@ test_files:
|
|
102
107
|
- spec/unit/assertions_spec.rb
|
103
108
|
- spec/unit/execution_time_spec.rb
|
104
109
|
- spec/unit/iteration_spec.rb
|
105
|
-
has_rdoc:
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
---
|
2
|
-
language: ruby
|
3
|
-
sudo: false
|
4
|
-
cache: bundler
|
5
|
-
script: "bundle exec rake ci"
|
6
|
-
rvm:
|
7
|
-
- 2.0.0
|
8
|
-
- 2.1.10
|
9
|
-
- 2.2.5
|
10
|
-
- 2.3.1
|
11
|
-
- ruby-head
|
12
|
-
- rbx
|
13
|
-
matrix:
|
14
|
-
include:
|
15
|
-
- rvm: jruby
|
16
|
-
env: JRUBY_OPTS='--server -Xcompile.invokedynamic=false -Xcompat.version=2.0'
|
17
|
-
- rvm: jruby-9.1.2.0
|
18
|
-
env: JRUBY_OPTS='--server -Xcompile.invokedynamic=false'
|
19
|
-
allow_failures:
|
20
|
-
- rvm: rbx
|
21
|
-
- rvm: ruby-head
|
22
|
-
- rvm: jruby-head
|
23
|
-
env: JRUBY_OPTS='--server -Xcompile.invokedynamic=false'
|
24
|
-
fast_finish: true
|
25
|
-
branches:
|
26
|
-
only: master
|
27
|
-
notifications:
|
28
|
-
email: false
|
data/Gemfile
DELETED