benchmark_driver 0.14.13 → 0.14.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +2 -2
- data/lib/benchmark_driver/metric.rb +1 -0
- data/lib/benchmark_driver/output.rb +4 -2
- data/lib/benchmark_driver/output/all.rb +104 -0
- data/lib/benchmark_driver/repeater.rb +27 -10
- data/lib/benchmark_driver/runner/command_stdout.rb +2 -2
- data/lib/benchmark_driver/runner/ips.rb +8 -2
- data/lib/benchmark_driver/runner/memory.rb +2 -2
- data/lib/benchmark_driver/runner/ruby_stdout.rb +7 -2
- data/lib/benchmark_driver/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 576179b82e3d7f201f8a58373e279219b2a20ffc7a74bb6133b09655db54ec45
|
4
|
+
data.tar.gz: c57f3b432fd5f7309f6bba0e318b75e425bb8e1e17e70916eed60b8e7a3b7785
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df832e8687b266851d5339039fa2e3a2b53d49ce8a25e5f2d7cf2c7691bd7f8c8394148c1d3de4c8dd0c7b5ab6d97f7a8e0ea923914478b7afc358c3d731178a
|
7
|
+
data.tar.gz: 569980b49fbcaf4515698f0519d7aa025bfe9d4acf7281d7d34cd85324e5afd0622b194417d744da1526b6ab2d7b5a15cc89c69d4cef9154650822231ab1df48
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# v0.14.14
|
2
|
+
|
3
|
+
- Add `all` output plugin to compare all sorted results
|
4
|
+
|
1
5
|
# v0.14.13
|
2
6
|
|
3
7
|
- Add macOS support to memory runner
|
@@ -87,7 +91,7 @@
|
|
87
91
|
|
88
92
|
- Add support for benchmark with different versions of gems and preludes
|
89
93
|
- Only YAML is supported for now, Ruby interface will come later
|
90
|
-
- [breaking change] Runner plugin interface is
|
94
|
+
- [breaking change] Runner plugin interface is slightly changed
|
91
95
|
|
92
96
|
# v0.12.0
|
93
97
|
|
data/README.md
CHANGED
@@ -272,7 +272,7 @@ ips, time, memory, once
|
|
272
272
|
|:-------|:------------|
|
273
273
|
| ips | Iteration per second (default) |
|
274
274
|
| time | Elapsed seconds |
|
275
|
-
| memory | Max resident set. This is supported only on Linux for now. |
|
275
|
+
| memory | Max resident set. This is supported only on Linux and macOS for now. |
|
276
276
|
| once | Forces `loop_count` to 1 for testing |
|
277
277
|
| ruby\_stdout | Special runner to integrate existing benchmarks |
|
278
278
|
|
@@ -360,7 +360,7 @@ See following example:
|
|
360
360
|
|
361
361
|
* https://github.com/benchmark-driver/optcarrot
|
362
362
|
|
363
|
-
If
|
363
|
+
If your benchmark can run with `ruby foo bar`, specify `foo bar` to `command:`.
|
364
364
|
Then write `stdout_to_metrics:` to convert stdout to metrics. This runner can be used only with YAML interface for now.
|
365
365
|
|
366
366
|
```
|
@@ -30,6 +30,7 @@ module BenchmarkDriver
|
|
30
30
|
# Everything that can be known after running benchmark
|
31
31
|
Result = ::BenchmarkDriver::Struct.new(
|
32
32
|
:values, # @param [Hash{ BenchmarkDriver::Metric => Float }] - Main benchmark results
|
33
|
+
:all_values, # @param [Hash{ BenchmarkDriver::Metric => Float }] - All benchmark results. Used by --output=all (optional)
|
33
34
|
:duration, # @param [Float,nil] - Time taken to run the benchmark job (optional)
|
34
35
|
:loop_count, # @param [Integer,nil] - Times to run the benchmark job (optional)
|
35
36
|
:environment, # @param [Hash] - Any other key -> value pairs to express the benchmark context
|
@@ -73,11 +73,13 @@ module BenchmarkDriver
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
# @param [Float]
|
76
|
+
# @param [Hash{ BenchmarkDriver::Metric => Float }] values
|
77
|
+
# @param [Hash{ BenchmarkDriver::Metric => [Float] },nil] values
|
77
78
|
# @param [BenchmarkDriver::Metric] metic
|
78
|
-
def report(values:, duration: nil, loop_count: nil, environment: {})
|
79
|
+
def report(values:, all_values: nil, duration: nil, loop_count: nil, environment: {})
|
79
80
|
result = BenchmarkDriver::Result.new(
|
80
81
|
values: values,
|
82
|
+
all_values: all_values,
|
81
83
|
duration: duration,
|
82
84
|
loop_count: loop_count,
|
83
85
|
environment: environment,
|
@@ -0,0 +1,104 @@
|
|
1
|
+
class BenchmarkDriver::Output::All
|
2
|
+
NAME_LENGTH = 20
|
3
|
+
CONTEXT_LENGTH = 20
|
4
|
+
|
5
|
+
# @param [Array<BenchmarkDriver::Metric>] metrics
|
6
|
+
# @param [Array<BenchmarkDriver::Job>] jobs
|
7
|
+
# @param [Array<BenchmarkDriver::Context>] contexts
|
8
|
+
def initialize(metrics:, jobs:, contexts:)
|
9
|
+
@metrics = metrics
|
10
|
+
@job_names = jobs.map(&:name)
|
11
|
+
@context_names = contexts.map(&:name)
|
12
|
+
@name_length = [@job_names.map(&:length).max, NAME_LENGTH].max
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_warmup(&block)
|
16
|
+
without_stdout_buffering do
|
17
|
+
$stdout.puts 'Warming up --------------------------------------'
|
18
|
+
# TODO: show exec name if it has multiple ones
|
19
|
+
block.call
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_benchmark(&block)
|
24
|
+
@job_context_result = Hash.new do |hash, job|
|
25
|
+
hash[job] = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
result = without_stdout_buffering do
|
29
|
+
$stdout.puts 'Calculating -------------------------------------'
|
30
|
+
if @context_names.size > 1
|
31
|
+
$stdout.print(' ' * @name_length)
|
32
|
+
@context_names.each do |context_name|
|
33
|
+
$stdout.print(" %#{CONTEXT_LENGTH}s " % context_name)
|
34
|
+
end
|
35
|
+
$stdout.puts
|
36
|
+
end
|
37
|
+
|
38
|
+
block.call
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param [BenchmarkDriver::Job] job
|
44
|
+
def with_job(job, &block)
|
45
|
+
@job_name = "%#{@name_length}s" % job.name
|
46
|
+
$stdout.print(@job_name)
|
47
|
+
@context_values = {}
|
48
|
+
block.call
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param [BenchmarkDriver::Context] context
|
52
|
+
def with_context(context, &block)
|
53
|
+
@context = context
|
54
|
+
block.call
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param [BenchmarkDriver::Result] result
|
58
|
+
def report(result)
|
59
|
+
if result.all_values.nil? || !defined?(@context_values)
|
60
|
+
$stdout.puts(" %#{[CONTEXT_LENGTH, @context.name.length].max}s " % result.values.values.first.to_s)
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
num_values = result.all_values.values.first.size
|
65
|
+
if @context_values.empty?
|
66
|
+
print("\r")
|
67
|
+
else
|
68
|
+
print("\e[#{num_values}F")
|
69
|
+
end
|
70
|
+
@context_values[@context] = result.all_values.values.first.sort
|
71
|
+
|
72
|
+
precision = result.values.values.first.to_s.sub(/\A\d+\./, '').length
|
73
|
+
num_values.times do |i|
|
74
|
+
if i == 0
|
75
|
+
$stdout.print(@job_name)
|
76
|
+
else
|
77
|
+
print(" " * [@job_name.length, NAME_LENGTH].max)
|
78
|
+
end
|
79
|
+
|
80
|
+
@context_values.each do |context, values|
|
81
|
+
$stdout.print(" %#{[CONTEXT_LENGTH, context.name.length].max}.#{precision}f " % values[i])
|
82
|
+
end
|
83
|
+
(@context_names - @context_values.keys.map(&:name)).each do |context_name|
|
84
|
+
print(" " * ([CONTEXT_LENGTH, context_name.length].max + 2))
|
85
|
+
end
|
86
|
+
|
87
|
+
if i == 0
|
88
|
+
$stdout.puts(@metrics.first.unit)
|
89
|
+
else
|
90
|
+
$stdout.puts
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
# benchmark_driver ouputs logs ASAP. This enables sync flag for it.
|
98
|
+
def without_stdout_buffering
|
99
|
+
sync, $stdout.sync = $stdout.sync, true
|
100
|
+
yield
|
101
|
+
ensure
|
102
|
+
$stdout.sync = sync
|
103
|
+
end
|
104
|
+
end
|
@@ -1,25 +1,36 @@
|
|
1
|
+
require 'benchmark_driver/struct'
|
2
|
+
|
1
3
|
module BenchmarkDriver
|
2
4
|
# Repeat calling block and return desired result: "best", "worst" or "average".
|
3
5
|
module Repeater
|
4
6
|
VALID_TYPES = %w[best worst average]
|
5
7
|
|
8
|
+
RepeatResult = ::BenchmarkDriver::Struct.new(
|
9
|
+
:value, # the value desired by --repeat-result
|
10
|
+
:all_values, # all benchmark results. Used by --output=all.
|
11
|
+
)
|
12
|
+
|
6
13
|
class << self
|
7
14
|
# `block.call` can return multiple objects, but the first one is used for sort.
|
8
15
|
# When `config.repeat_result == 'average'`, how to deal with rest objects is decided
|
9
16
|
# by `:rest_on_average` option.
|
17
|
+
#
|
18
|
+
# @param [Proc] block - returns Float or [Float, ...]
|
10
19
|
def with_repeat(config:, larger_better:, rest_on_average: :first, &block)
|
11
20
|
values = config.repeat_count.times.map { block.call }
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
desired_value =
|
23
|
+
case config.repeat_result
|
24
|
+
when 'best'
|
25
|
+
best_result(values, larger_better)
|
26
|
+
when 'worst'
|
27
|
+
best_result(values, !larger_better)
|
28
|
+
when 'average'
|
29
|
+
average_result(values, rest_on_average)
|
30
|
+
else
|
31
|
+
raise "unexpected repeat_result #{config.repeat_result.inspect}"
|
32
|
+
end
|
33
|
+
RepeatResult.new(value: desired_value, all_values: extract_values(values))
|
23
34
|
end
|
24
35
|
|
25
36
|
private
|
@@ -47,6 +58,12 @@ module BenchmarkDriver
|
|
47
58
|
raise "unexpected rest_on_average #{rest_on_average.inspect}"
|
48
59
|
end
|
49
60
|
end
|
61
|
+
|
62
|
+
def extract_values(values)
|
63
|
+
values.map do |value|
|
64
|
+
value.is_a?(Array) ? value.first : value
|
65
|
+
end
|
66
|
+
end
|
50
67
|
end
|
51
68
|
end
|
52
69
|
end
|
@@ -64,7 +64,7 @@ class BenchmarkDriver::Runner::CommandStdout
|
|
64
64
|
@output.with_job(name: job.name) do
|
65
65
|
@contexts.each do |context|
|
66
66
|
exec = context.executable
|
67
|
-
|
67
|
+
result = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: metric.larger_better) do
|
68
68
|
stdout = with_chdir(job.working_directory) do
|
69
69
|
with_ruby_prefix(exec) { execute(*exec.command, *job.command) }
|
70
70
|
end
|
@@ -75,7 +75,7 @@ class BenchmarkDriver::Runner::CommandStdout
|
|
75
75
|
end
|
76
76
|
|
77
77
|
@output.with_context(name: exec.name, executable: exec) do
|
78
|
-
@output.report(values: { metric => value })
|
78
|
+
@output.report(values: { metric => result.value }, all_values: { metric => result.all_values })
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -52,11 +52,17 @@ class BenchmarkDriver::Runner::Ips
|
|
52
52
|
@output.with_job(name: job.name) do
|
53
53
|
job.runnable_contexts(@contexts).each do |context|
|
54
54
|
repeat_params = { config: @config, larger_better: true, rest_on_average: :average }
|
55
|
-
|
55
|
+
result = BenchmarkDriver::Repeater.with_repeat(repeat_params) do
|
56
56
|
run_benchmark(job, context: context)
|
57
57
|
end
|
58
|
+
value, duration = result.value
|
58
59
|
@output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do
|
59
|
-
@output.report(
|
60
|
+
@output.report(
|
61
|
+
values: { metric => value },
|
62
|
+
all_values: { metric => result.all_values },
|
63
|
+
duration: duration,
|
64
|
+
loop_count: job.loop_count,
|
65
|
+
)
|
60
66
|
end
|
61
67
|
end
|
62
68
|
end
|
@@ -48,11 +48,11 @@ class BenchmarkDriver::Runner::Memory
|
|
48
48
|
jobs.each do |job|
|
49
49
|
@output.with_job(name: job.name) do
|
50
50
|
job.runnable_contexts(@contexts).each do |context|
|
51
|
-
|
51
|
+
result = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: false) do
|
52
52
|
run_benchmark(job, context: context)
|
53
53
|
end
|
54
54
|
@output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do
|
55
|
-
@output.report(values: { METRIC => value }, loop_count: job.loop_count)
|
55
|
+
@output.report(values: { METRIC => result.value }, all_values: { METRIC => result.all_values }, loop_count: job.loop_count)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -82,7 +82,7 @@ class BenchmarkDriver::Runner::RubyStdout
|
|
82
82
|
@contexts.each do |context|
|
83
83
|
exec = context.executable
|
84
84
|
repeat_params = { config: @config, larger_better: metric.larger_better }
|
85
|
-
|
85
|
+
result = BenchmarkDriver::Repeater.with_repeat(repeat_params) do
|
86
86
|
stdout = with_chdir(job.working_directory) do
|
87
87
|
with_ruby_prefix(exec) { execute(*exec.command, *job.command) }
|
88
88
|
end
|
@@ -93,9 +93,14 @@ class BenchmarkDriver::Runner::RubyStdout
|
|
93
93
|
)
|
94
94
|
[script.value, script.environment]
|
95
95
|
end
|
96
|
+
value, environment = result.value
|
96
97
|
|
97
98
|
@output.with_context(name: exec.name, executable: exec) do
|
98
|
-
@output.report(
|
99
|
+
@output.report(
|
100
|
+
values: { metric => value },
|
101
|
+
all_values: { metric => result.all_values },
|
102
|
+
environment: environment,
|
103
|
+
)
|
99
104
|
end
|
100
105
|
end
|
101
106
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: benchmark_driver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takashi Kokubun
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -106,6 +106,7 @@ files:
|
|
106
106
|
- lib/benchmark_driver/job_parser.rb
|
107
107
|
- lib/benchmark_driver/metric.rb
|
108
108
|
- lib/benchmark_driver/output.rb
|
109
|
+
- lib/benchmark_driver/output/all.rb
|
109
110
|
- lib/benchmark_driver/output/compare.rb
|
110
111
|
- lib/benchmark_driver/output/markdown.rb
|
111
112
|
- lib/benchmark_driver/output/record.rb
|
@@ -142,8 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
143
|
- !ruby/object:Gem::Version
|
143
144
|
version: '0'
|
144
145
|
requirements: []
|
145
|
-
|
146
|
-
rubygems_version: 2.7.6
|
146
|
+
rubygems_version: 3.0.3
|
147
147
|
signing_key:
|
148
148
|
specification_version: 4
|
149
149
|
summary: Fully-featured accurate benchmark driver for Ruby
|