benchmark_driver 0.8.6 → 0.9.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/.travis.yml +1 -3
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -6
- data/README.md +51 -52
- data/benchmark_driver.gemspec +3 -2
- data/bin/console +4 -11
- data/examples/exec_blank.rb +2 -2
- data/examples/exec_blank_simple.rb +2 -3
- data/exe/benchmark-driver +74 -83
- data/lib/benchmark_driver.rb +12 -1
- data/lib/benchmark_driver/config.rb +36 -0
- data/lib/benchmark_driver/default_job.rb +12 -0
- data/lib/benchmark_driver/default_job_parser.rb +68 -0
- data/lib/benchmark_driver/job_parser.rb +42 -0
- data/lib/benchmark_driver/metrics.rb +17 -0
- data/lib/benchmark_driver/output.rb +27 -0
- data/lib/benchmark_driver/output/compare.rb +196 -0
- data/lib/benchmark_driver/output/markdown.rb +102 -0
- data/lib/benchmark_driver/output/simple.rb +97 -0
- data/lib/benchmark_driver/rbenv.rb +11 -0
- data/lib/benchmark_driver/ruby_interface.rb +51 -0
- data/lib/benchmark_driver/runner.rb +42 -0
- data/lib/benchmark_driver/runner/ips.rb +239 -0
- data/lib/benchmark_driver/runner/memory.rb +142 -0
- data/lib/benchmark_driver/runner/time.rb +18 -0
- data/lib/benchmark_driver/struct.rb +85 -0
- data/lib/benchmark_driver/version.rb +3 -0
- metadata +21 -33
- data/bin/bench +0 -4
- data/examples/call.rb +0 -12
- data/examples/call_blank.rb +0 -13
- data/examples/call_erb.rb +0 -33
- data/examples/call_interpolation.rb +0 -13
- data/examples/eval_blank.rb +0 -12
- data/examples/eval_blank_loop.rb +0 -13
- data/examples/eval_interpolation.rb +0 -15
- data/lib/benchmark/driver.rb +0 -101
- data/lib/benchmark/driver/benchmark_result.rb +0 -21
- data/lib/benchmark/driver/bundle_installer.rb +0 -45
- data/lib/benchmark/driver/bundler.rb +0 -12
- data/lib/benchmark/driver/configuration.rb +0 -77
- data/lib/benchmark/driver/duration_runner.rb +0 -24
- data/lib/benchmark/driver/error.rb +0 -16
- data/lib/benchmark/driver/repeatable_runner.rb +0 -18
- data/lib/benchmark/driver/ruby_dsl_parser.rb +0 -78
- data/lib/benchmark/driver/time.rb +0 -12
- data/lib/benchmark/driver/version.rb +0 -5
- data/lib/benchmark/driver/yaml_parser.rb +0 -55
- data/lib/benchmark/output.rb +0 -20
- data/lib/benchmark/output/ips.rb +0 -143
- data/lib/benchmark/output/markdown.rb +0 -73
- data/lib/benchmark/output/memory.rb +0 -57
- data/lib/benchmark/output/time.rb +0 -57
- data/lib/benchmark/runner.rb +0 -14
- data/lib/benchmark/runner/call.rb +0 -97
- data/lib/benchmark/runner/eval.rb +0 -147
- data/lib/benchmark/runner/exec.rb +0 -193
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'benchmark_driver/runner/ips'
|
2
|
+
|
3
|
+
class BenchmarkDriver::Runner::Time < BenchmarkDriver::Runner::Ips
|
4
|
+
# JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job"
|
5
|
+
Job = Class.new(BenchmarkDriver::DefaultJob)
|
6
|
+
# Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
|
7
|
+
JobParser = BenchmarkDriver::DefaultJobParser.for(Job)
|
8
|
+
# Passed to `output` by `BenchmarkDriver::Runner.run`
|
9
|
+
MetricsType = BenchmarkDriver::Metrics::Type.new(unit: 's')
|
10
|
+
|
11
|
+
# Overriding BenchmarkDriver::Runner::Ips#build_metrics
|
12
|
+
def build_metrics(duration:, executable:, loop_count:)
|
13
|
+
BenchmarkDriver::Metrics.new(
|
14
|
+
value: duration,
|
15
|
+
executable: executable,
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Extended Struct with:
|
2
|
+
# * Polyfilled `keyword_init: true`
|
3
|
+
# * Default value configuration
|
4
|
+
# * Deeply freezing members
|
5
|
+
module BenchmarkDriver
|
6
|
+
class << Struct = Module.new
|
7
|
+
# @param [Array<Symbol>] args
|
8
|
+
# @param [Hash{ Symbol => Object }] defaults
|
9
|
+
def new(*args, defaults: {}, &block)
|
10
|
+
# Polyfill `keyword_init: true`
|
11
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
|
12
|
+
klass = ::Struct.new(*args, keyword_init: true, &block)
|
13
|
+
else
|
14
|
+
klass = keyword_init_struct(*args, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Default value config
|
18
|
+
configure_defaults(klass, defaults)
|
19
|
+
|
20
|
+
# Force deeply freezing members
|
21
|
+
force_deep_freeze(klass)
|
22
|
+
|
23
|
+
klass
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Polyfill for Ruby < 2.5.0
|
29
|
+
def keyword_init_struct(*args, &block)
|
30
|
+
::Struct.new(*args).tap do |klass|
|
31
|
+
klass.prepend(Module.new {
|
32
|
+
# @param [Hash{ Symbol => Object }] args
|
33
|
+
def initialize(**args)
|
34
|
+
args.each do |key, value|
|
35
|
+
unless members.include?(key)
|
36
|
+
raise ArgumentError.new("unknwon keywords: #{key}")
|
37
|
+
next
|
38
|
+
end
|
39
|
+
|
40
|
+
public_send("#{key}=", value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
})
|
44
|
+
klass.prepend(Module.new(&block))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def configure_defaults(klass, defaults)
|
49
|
+
class << klass
|
50
|
+
attr_accessor :defaults
|
51
|
+
end
|
52
|
+
klass.defaults = defaults
|
53
|
+
|
54
|
+
klass.prepend(Module.new {
|
55
|
+
def initialize(**)
|
56
|
+
super
|
57
|
+
self.class.defaults.each do |key, value|
|
58
|
+
if public_send(key).nil?
|
59
|
+
public_send("#{key}=", value)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
})
|
64
|
+
|
65
|
+
def klass.inherited(child)
|
66
|
+
child.defaults = self.defaults
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def force_deep_freeze(klass)
|
71
|
+
klass.class_eval do
|
72
|
+
def freeze
|
73
|
+
members.each do |member|
|
74
|
+
value = public_send(member)
|
75
|
+
if value.is_a?(Array)
|
76
|
+
value.each(&:freeze)
|
77
|
+
end
|
78
|
+
value.freeze
|
79
|
+
end
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
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.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takashi Kokubun
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -54,16 +54,8 @@ files:
|
|
54
54
|
- README.md
|
55
55
|
- Rakefile
|
56
56
|
- benchmark_driver.gemspec
|
57
|
-
- bin/bench
|
58
57
|
- bin/console
|
59
58
|
- bin/setup
|
60
|
-
- examples/call.rb
|
61
|
-
- examples/call_blank.rb
|
62
|
-
- examples/call_erb.rb
|
63
|
-
- examples/call_interpolation.rb
|
64
|
-
- examples/eval_blank.rb
|
65
|
-
- examples/eval_blank_loop.rb
|
66
|
-
- examples/eval_interpolation.rb
|
67
59
|
- examples/exec_blank.rb
|
68
60
|
- examples/exec_blank_simple.rb
|
69
61
|
- examples/yaml/array_duration_time.yml
|
@@ -76,28 +68,24 @@ files:
|
|
76
68
|
- examples/yaml/example_multi.yml
|
77
69
|
- examples/yaml/example_single.yml
|
78
70
|
- exe/benchmark-driver
|
79
|
-
- lib/benchmark/driver.rb
|
80
|
-
- lib/benchmark/driver/benchmark_result.rb
|
81
|
-
- lib/benchmark/driver/bundle_installer.rb
|
82
|
-
- lib/benchmark/driver/bundler.rb
|
83
|
-
- lib/benchmark/driver/configuration.rb
|
84
|
-
- lib/benchmark/driver/duration_runner.rb
|
85
|
-
- lib/benchmark/driver/error.rb
|
86
|
-
- lib/benchmark/driver/repeatable_runner.rb
|
87
|
-
- lib/benchmark/driver/ruby_dsl_parser.rb
|
88
|
-
- lib/benchmark/driver/time.rb
|
89
|
-
- lib/benchmark/driver/version.rb
|
90
|
-
- lib/benchmark/driver/yaml_parser.rb
|
91
|
-
- lib/benchmark/output.rb
|
92
|
-
- lib/benchmark/output/ips.rb
|
93
|
-
- lib/benchmark/output/markdown.rb
|
94
|
-
- lib/benchmark/output/memory.rb
|
95
|
-
- lib/benchmark/output/time.rb
|
96
|
-
- lib/benchmark/runner.rb
|
97
|
-
- lib/benchmark/runner/call.rb
|
98
|
-
- lib/benchmark/runner/eval.rb
|
99
|
-
- lib/benchmark/runner/exec.rb
|
100
71
|
- lib/benchmark_driver.rb
|
72
|
+
- lib/benchmark_driver/config.rb
|
73
|
+
- lib/benchmark_driver/default_job.rb
|
74
|
+
- lib/benchmark_driver/default_job_parser.rb
|
75
|
+
- lib/benchmark_driver/job_parser.rb
|
76
|
+
- lib/benchmark_driver/metrics.rb
|
77
|
+
- lib/benchmark_driver/output.rb
|
78
|
+
- lib/benchmark_driver/output/compare.rb
|
79
|
+
- lib/benchmark_driver/output/markdown.rb
|
80
|
+
- lib/benchmark_driver/output/simple.rb
|
81
|
+
- lib/benchmark_driver/rbenv.rb
|
82
|
+
- lib/benchmark_driver/ruby_interface.rb
|
83
|
+
- lib/benchmark_driver/runner.rb
|
84
|
+
- lib/benchmark_driver/runner/ips.rb
|
85
|
+
- lib/benchmark_driver/runner/memory.rb
|
86
|
+
- lib/benchmark_driver/runner/time.rb
|
87
|
+
- lib/benchmark_driver/struct.rb
|
88
|
+
- lib/benchmark_driver/version.rb
|
101
89
|
homepage: https://github.com/k0kubun/benchmark_driver
|
102
90
|
licenses:
|
103
91
|
- MIT
|
@@ -110,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
98
|
requirements:
|
111
99
|
- - ">="
|
112
100
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
101
|
+
version: 2.1.0
|
114
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
103
|
requirements:
|
116
104
|
- - ">="
|
@@ -118,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
106
|
version: '0'
|
119
107
|
requirements: []
|
120
108
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.
|
109
|
+
rubygems_version: 2.6.13
|
122
110
|
signing_key:
|
123
111
|
specification_version: 4
|
124
112
|
summary: Fully-featured accurate benchmark driver for Ruby
|
data/bin/bench
DELETED
data/examples/call.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'benchmark/driver'
|
2
|
-
|
3
|
-
Benchmark.driver do |x|
|
4
|
-
large_a = "Hellooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
5
|
-
large_b = "Wooooooooooooooooooooooooooooooooooooooooooooooooooorld"
|
6
|
-
|
7
|
-
small_a = "Hello"
|
8
|
-
small_b = "World"
|
9
|
-
|
10
|
-
x.report('large') { "#{large_a}, #{large_b}!" }
|
11
|
-
x.report('small') { "#{small_a}, #{small_b}!" }
|
12
|
-
end
|
data/examples/call_blank.rb
DELETED
data/examples/call_erb.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'benchmark/driver'
|
2
|
-
require 'erb'
|
3
|
-
require 'erubi'
|
4
|
-
require 'erubis'
|
5
|
-
|
6
|
-
data = DATA.read
|
7
|
-
|
8
|
-
mod = Module.new
|
9
|
-
mod.instance_eval("def self.erb(title, content); #{ERB.new(data).src}; end", "(ERB)")
|
10
|
-
mod.instance_eval("def self.erubis(title, content); #{Erubi::Engine.new(data).src}; end", "(Erubi)")
|
11
|
-
mod.instance_eval("def self.erubi(title, content); #{Erubis::Eruby.new(data).src}; end", "(Erubis)")
|
12
|
-
|
13
|
-
title = "hello world!"
|
14
|
-
content = "hello world!\n" * 10
|
15
|
-
|
16
|
-
Benchmark.driver do |x|
|
17
|
-
x.report("ERB #{RUBY_VERSION}") { mod.erb(title, content) }
|
18
|
-
x.report("Erubis #{Erubis::VERSION}") { mod.erubis(title, content) }
|
19
|
-
x.report("Erubi #{Erubi::VERSION}") { mod.erubi(title, content) }
|
20
|
-
x.compare!
|
21
|
-
end
|
22
|
-
|
23
|
-
__END__
|
24
|
-
|
25
|
-
<html>
|
26
|
-
<head> <%= title %> </head>
|
27
|
-
<body>
|
28
|
-
<h1> <%= title %> </h1>
|
29
|
-
<p>
|
30
|
-
<%= content %>
|
31
|
-
</p>
|
32
|
-
</body>
|
33
|
-
</html>
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'benchmark/driver'
|
2
|
-
|
3
|
-
Benchmark.driver do |x|
|
4
|
-
large_a = "Hellooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
5
|
-
large_b = "Wooooooooooooooooooooooooooooooooooooooooooooooooooorld"
|
6
|
-
|
7
|
-
small_a = "Hello"
|
8
|
-
small_b = "World"
|
9
|
-
|
10
|
-
x.report('large') { "#{large_a}, #{large_b}!" }
|
11
|
-
x.report('small') { "#{small_a}, #{small_b}!" }
|
12
|
-
x.compare!
|
13
|
-
end
|
data/examples/eval_blank.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'benchmark/driver'
|
2
|
-
|
3
|
-
class Array
|
4
|
-
alias_method :blank?, :empty?
|
5
|
-
end
|
6
|
-
|
7
|
-
Benchmark.driver(runner: :eval) do |x|
|
8
|
-
x.prelude %{ array = [] }
|
9
|
-
x.report 'Array#empty?', %{ array.empty? }
|
10
|
-
x.report 'Array#blank?', %{ array.blank? }
|
11
|
-
x.compare!
|
12
|
-
end
|
data/examples/eval_blank_loop.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'benchmark/driver'
|
2
|
-
|
3
|
-
class Array
|
4
|
-
alias_method :blank?, :empty?
|
5
|
-
end
|
6
|
-
|
7
|
-
Benchmark.driver do |x|
|
8
|
-
x.prelude %{ array = [] }
|
9
|
-
x.report 'Array#empty?', %{ array.empty? }
|
10
|
-
x.report 'Array#blank?', %{ array.blank? }
|
11
|
-
x.loop_count 10000000
|
12
|
-
x.compare!
|
13
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'benchmark/driver'
|
2
|
-
|
3
|
-
Benchmark.driver do |x|
|
4
|
-
x.prelude <<-EOS
|
5
|
-
large_a = "Hellooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
6
|
-
large_b = "Wooooooooooooooooooooooooooooooooooooooooooooooooooorld"
|
7
|
-
|
8
|
-
small_a = "Hello"
|
9
|
-
small_b = "World"
|
10
|
-
EOS
|
11
|
-
|
12
|
-
x.report('large', '"#{large_a}, #{large_b}!"')
|
13
|
-
x.report('small', '"#{small_a}, #{small_b}!"')
|
14
|
-
x.compare!
|
15
|
-
end
|
data/lib/benchmark/driver.rb
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
module Benchmark
|
2
|
-
# RubyDriver entrypoint.
|
3
|
-
def self.driver(*args, &block)
|
4
|
-
dsl = Driver::RubyDslParser.new(*args)
|
5
|
-
block.call(dsl)
|
6
|
-
|
7
|
-
Driver.run(dsl.configuration)
|
8
|
-
end
|
9
|
-
|
10
|
-
module Driver
|
11
|
-
class InvalidConfig < StandardError; end
|
12
|
-
|
13
|
-
class << self
|
14
|
-
# Main function which is used by both RubyDriver and YamlDriver.
|
15
|
-
# @param [Benchmark::Driver::Configuration] config
|
16
|
-
def run(config)
|
17
|
-
validate_config(config)
|
18
|
-
if config.runner_options.type.nil?
|
19
|
-
config.runner_options.type = runner_type_for(config)
|
20
|
-
end
|
21
|
-
|
22
|
-
if config.runner_options.bundler
|
23
|
-
config.runner_options.executables.each do |executable|
|
24
|
-
Benchmark::Driver::BundleInstaller.bundle_install_for(executable)
|
25
|
-
executable.command << '-rbundler/setup'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
runner_class = Runner.find(config.runner_options.type)
|
30
|
-
output_class = Output.find(config.output_options.type)
|
31
|
-
|
32
|
-
missing_fields = output_class::REQUIRED_FIELDS - runner_class::SUPPORTED_FIELDS
|
33
|
-
unless missing_fields.empty?
|
34
|
-
raise ArgumentError.new(
|
35
|
-
"#{output_class.name} requires #{missing_fields.inspect} fields "\
|
36
|
-
"which are not supported by #{runner_class.name}. Try using another runner."
|
37
|
-
)
|
38
|
-
end
|
39
|
-
|
40
|
-
without_stdout_buffering do
|
41
|
-
runner = runner_class.new(
|
42
|
-
config.runner_options,
|
43
|
-
output: output_class.new(
|
44
|
-
jobs: config.jobs,
|
45
|
-
executables: config.runner_options.executables,
|
46
|
-
options: config.output_options,
|
47
|
-
),
|
48
|
-
)
|
49
|
-
runner.run(config)
|
50
|
-
end
|
51
|
-
rescue Benchmark::Driver::Error => e
|
52
|
-
$stderr.puts "\n\nFailed to execute benchmark!\n\n#{e.class.name}:\n #{e.message}"
|
53
|
-
exit 1
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def validate_config(config)
|
59
|
-
if config.jobs.empty?
|
60
|
-
raise InvalidConfig.new('No benchmark script is specified')
|
61
|
-
end
|
62
|
-
|
63
|
-
script_class = config.jobs.first.script.class
|
64
|
-
unless config.jobs.all? { |j| j.script.is_a?(script_class) }
|
65
|
-
raise InvalidConfig.new('Benchmark scripts include both String and Proc. Only either of them should be specified.')
|
66
|
-
end
|
67
|
-
|
68
|
-
# TODO: invalidate prelude for call runner
|
69
|
-
end
|
70
|
-
|
71
|
-
def runner_type_for(config)
|
72
|
-
script_class = config.jobs.first.script.class
|
73
|
-
if script_class == Proc
|
74
|
-
:call
|
75
|
-
elsif config.runner_options.executables_specified?
|
76
|
-
:exec
|
77
|
-
else
|
78
|
-
:eval
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# benchmark_driver ouputs logs ASAP. This enables sync flag for it.
|
83
|
-
#
|
84
|
-
# Currently benchmark_driver supports only output to stdout.
|
85
|
-
# In future exetension, this may be included in Output plugins.
|
86
|
-
def without_stdout_buffering
|
87
|
-
sync, $stdout.sync = $stdout.sync, true
|
88
|
-
yield
|
89
|
-
ensure
|
90
|
-
$stdout.sync = sync
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
require 'benchmark/output'
|
97
|
-
require 'benchmark/runner'
|
98
|
-
require 'benchmark/driver/bundle_installer'
|
99
|
-
require 'benchmark/driver/error'
|
100
|
-
require 'benchmark/driver/ruby_dsl_parser'
|
101
|
-
require 'benchmark/driver/version'
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# @param [Benchmark::Driver::Configuration::Job] job
|
2
|
-
# @param [Integer] iterations - Executed iterations of benchmark script in the job
|
3
|
-
# @param [Float] real - Real time taken by the job
|
4
|
-
# @param [Integer] max_rss - Maximum resident set size of the process during its lifetime, in Kilobytes.
|
5
|
-
class Benchmark::Driver::BenchmarkResult < Struct.new(:job, :iterations, :real, :max_rss)
|
6
|
-
alias :duration :real
|
7
|
-
|
8
|
-
def ips
|
9
|
-
iterations / real
|
10
|
-
end
|
11
|
-
|
12
|
-
def ip100ms
|
13
|
-
ips / 10
|
14
|
-
end
|
15
|
-
|
16
|
-
def iterations
|
17
|
-
# runner's warmup uses `result.ips` to calculate `job.loop_count`, and thus
|
18
|
-
# at that moment `job.loop_count` isn't available and we need to use `super`.
|
19
|
-
super || job.loop_count
|
20
|
-
end
|
21
|
-
end
|