benchmark_driver 0.9.2 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d35c947c3b1718ea35b688a22546b6fcc28d6494219791ca9b990571a20ec60b
4
- data.tar.gz: 67335dcf0ddb2d881539f6ff7c3f565483a4bf4781829ffe75979276869b34ab
3
+ metadata.gz: 6b444be9753246263a4b3a65f0fe33a07c62f4a538008245fb8a17b2e809f7b6
4
+ data.tar.gz: e4a43fb02781c343e266e8c5644d8fc4edf1568de93d620e90500f027bb4418a
5
5
  SHA512:
6
- metadata.gz: 9d78acc25353ed4d06676671bff54a40256a0d6b90ff543ece4659931d9c775a5496445976a7e3d0ce25326c6164394004b8060a8d7d41def62bc75f7c79a06a
7
- data.tar.gz: c8b1e02f00655551d8ff4333ccfa7f887da69dae34902e9f525aeaf37a63633bd480556cb3b3a518941c71824afea28d054b736be81e9fb9ed97fb45c3aac377
6
+ metadata.gz: 4c512a0e7bb65debbb79b2f312db9852db1625cfd3a46cab847b81f0d3f85d09caef043e09b1f47679f6b476ea98d2a913ea7fbd1a694aac4621a2e701256450
7
+ data.tar.gz: 5fd294728cf04e4524a62aa12916ba4c66b6e9f8dab498cb290a20d324a3aa60b5f53786d6bb150ec1a44d730770a40d77ab8e3f29fcd5c109ed85f5e02c074c
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  /Gemfile.lock
10
+ benchmark_driver.record.yml
@@ -11,5 +11,4 @@ branches:
11
11
  - master
12
12
  before_install: gem install bundler -v 1.15.4
13
13
  script:
14
- - bundle exec rake ruby_examples
15
- - bundle exec rake yaml_examples
14
+ - bundle exec rake
@@ -1,3 +1,10 @@
1
+ # v0.10.0
2
+
3
+ - Add "record" output and "recorded" runner
4
+ - You can record metrics to yaml and change how to output later
5
+ - Change output interface to set metrics\_type
6
+ - Now runner needs to call `output#metrics_type=`
7
+
1
8
  # v0.9.2
2
9
 
3
10
  - Add `--verbose` option
data/Rakefile CHANGED
@@ -1,7 +1,31 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'shellwords'
3
3
 
4
- task :ruby_examples do
4
+ task :test do
5
+ blank_loop = File.expand_path('./examples/yaml/blank_loop.yml', __dir__) # no warmup
6
+ blank_hash = File.expand_path('./examples/yaml/blank_hash.yml', __dir__) # needs warmup
7
+ {
8
+ 'ips' => 'compare',
9
+ 'time' => 'simple',
10
+ 'memory' => 'simple',
11
+ 'once' => 'markdown',
12
+ }.each do |runner, output|
13
+ Bundler.with_clean_env do
14
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', blank_loop, '-r', runner, '-o', output].shelljoin
15
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', blank_hash, '-r', runner, '-o', output, '--run-duration', '1'].shelljoin
16
+ end
17
+ end
18
+ end
19
+
20
+ task :test_record do
21
+ blank_loop = File.expand_path('./examples/yaml/blank_loop.yml', __dir__) # no warmup
22
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', blank_loop, '-r', 'ips', '-o', 'record'].shelljoin
23
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', 'benchmark_driver.record.yml', '-o', 'compare'].shelljoin
24
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', 'benchmark_driver.record.yml', '-o', 'record'].shelljoin
25
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', 'benchmark_driver.record.yml', '-o', 'simple'].shelljoin
26
+ end
27
+
28
+ task :test_ruby do
5
29
  Dir.glob(File.expand_path('./examples/*.rb', __dir__)).sort.each do |file|
6
30
  Bundler.with_clean_env do
7
31
  sh ['time', 'bundle', 'exec', 'ruby', file].shelljoin
@@ -10,13 +34,13 @@ task :ruby_examples do
10
34
  end
11
35
  end
12
36
 
13
- task :yaml_examples do
37
+ task :test_yaml do
14
38
  Dir.glob(File.expand_path('./examples/yaml/*.yml', __dir__)).sort.each do |file|
15
39
  Bundler.with_clean_env do
16
- sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', file].shelljoin
40
+ sh ['time', 'bundle', 'exec', 'exe/benchmark-driver', file, '--run-duration', '1'].shelljoin
17
41
  end
18
42
  puts
19
43
  end
20
44
  end
21
45
 
22
- task default: [:ruby_examples, :yaml_examples]
46
+ task default: [:test, :test_record, :test_ruby, :test_yaml]
@@ -16,7 +16,7 @@ config = BenchmarkDriver::Config.new.tap do |c|
16
16
  abort '-r, --runner must take argument but not given' if d.nil?
17
17
  c.runner_type = d
18
18
  end
19
- o.on('-o', '--output [TYPE]', 'Specify output type: compare, simple, markdown (default: compare)') do |out|
19
+ o.on('-o', '--output [TYPE]', 'Specify output type: compare, simple, markdown, record (default: compare)') do |out|
20
20
  abort '-o, --output must take argument but not given' if out.nil?
21
21
  c.output_type = out
22
22
  end
@@ -2,7 +2,7 @@ require 'benchmark_driver/struct'
2
2
 
3
3
  module BenchmarkDriver
4
4
  DefaultJob = ::BenchmarkDriver::Struct.new(
5
- :name, # @param [String] name
5
+ :name, # @param [String] name - This is mandatory for all runner
6
6
  :script, # @param [String] benchmark
7
7
  :prelude, # @param [String,nil] prelude (optional)
8
8
  :teardown, # @param [String,nil] after (optional)
@@ -29,7 +29,12 @@ module BenchmarkDriver
29
29
  when Hash
30
30
  config.dup.tap do |hash|
31
31
  hash.keys.each do |key|
32
- hash[key.to_sym] = symbolize_keys(hash.delete(key))
32
+ case key
33
+ when String, Symbol
34
+ hash[key.to_sym] = symbolize_keys(hash.delete(key))
35
+ else # Struct
36
+ hash[key] = symbolize_keys(hash.delete(key))
37
+ end
33
38
  end
34
39
  end
35
40
  when Array
@@ -2,6 +2,7 @@ module BenchmarkDriver
2
2
  module Output
3
3
  require 'benchmark_driver/output/compare'
4
4
  require 'benchmark_driver/output/markdown'
5
+ require 'benchmark_driver/output/record'
5
6
  require 'benchmark_driver/output/simple'
6
7
  end
7
8
 
@@ -2,16 +2,16 @@
2
2
  class BenchmarkDriver::Output::Compare
3
3
  NAME_LENGTH = 20
4
4
 
5
+ # @param [BenchmarkDriver::Metrics::Type] metrics_type
6
+ attr_writer :metrics_type
7
+
5
8
  # @param [Array<BenchmarkDriver::*::Job>] jobs
6
9
  # @param [Array<BenchmarkDriver::Config::Executable>] executables
7
- # @param [BenchmarkDriver::Metrics::Type] metrics_type
8
- def initialize(jobs:, executables:, metrics_type:)
10
+ def initialize(jobs:, executables:)
9
11
  @jobs = jobs
10
12
  @executables = executables
11
- @metrics_type = metrics_type
12
13
  end
13
14
 
14
- # @param [BenchmarkDriver::Metrics] metrics
15
15
  def with_warmup(&block)
16
16
  without_stdout_buffering do
17
17
  $stdout.puts 'Warming up --------------------------------------'
@@ -20,7 +20,6 @@ class BenchmarkDriver::Output::Compare
20
20
  end
21
21
  end
22
22
 
23
- # @param [BenchmarkDriver::Metrics] metrics
24
23
  def with_benchmark(&block)
25
24
  @metrics_by_job = Hash.new { |h, k| h[k] = [] }
26
25
 
@@ -1,17 +1,17 @@
1
1
  class BenchmarkDriver::Output::Markdown
2
2
  NAME_LENGTH = 8
3
3
 
4
+ # @param [BenchmarkDriver::Metrics::Type] metrics_type
5
+ attr_writer :metrics_type
6
+
4
7
  # @param [Array<BenchmarkDriver::*::Job>] jobs
5
8
  # @param [Array<BenchmarkDriver::Config::Executable>] executables
6
- # @param [BenchmarkDriver::Metrics::Type] metrics_type
7
- def initialize(jobs:, executables:, metrics_type:)
9
+ def initialize(jobs:, executables:)
8
10
  @jobs = jobs
9
11
  @executables = executables
10
- @metrics_type = metrics_type
11
12
  @name_length = jobs.map { |j| j.name.size }.max
12
13
  end
13
14
 
14
- # @param [BenchmarkDriver::Metrics] metrics
15
15
  def with_warmup(&block)
16
16
  without_stdout_buffering do
17
17
  $stdout.print 'warming up'
@@ -21,7 +21,6 @@ class BenchmarkDriver::Output::Markdown
21
21
  $stdout.puts
22
22
  end
23
23
 
24
- # @param [BenchmarkDriver::Metrics] metrics
25
24
  def with_benchmark(&block)
26
25
  @with_benchmark = true
27
26
  without_stdout_buffering do
@@ -0,0 +1,59 @@
1
+ class BenchmarkDriver::Output::Record
2
+ # @param [BenchmarkDriver::Metrics::Type] metrics_type
3
+ attr_writer :metrics_type
4
+
5
+ # @param [Array<BenchmarkDriver::*::Job>] jobs
6
+ # @param [Array<BenchmarkDriver::Config::Executable>] executables
7
+ def initialize(jobs:, executables:)
8
+ @jobs = jobs
9
+ @executables = executables
10
+ @metrics_by_job = Hash.new do |h1, k1|
11
+ h1[k1] = Hash.new { |h2, k2| h2[k2] = [] }
12
+ end
13
+ end
14
+
15
+ def with_warmup(&block)
16
+ $stdout.print 'warming up'
17
+ block.call
18
+ ensure
19
+ $stdout.puts
20
+ end
21
+
22
+ def with_benchmark(&block)
23
+ @with_benchmark = true
24
+ $stdout.print 'benchmarking'
25
+ block.call
26
+ ensure
27
+ $stdout.puts
28
+ @with_benchmark = false
29
+ save_record
30
+ end
31
+
32
+ # @param [BenchmarkDriver::*::Job] job
33
+ def with_job(job, &block)
34
+ @current_job = job
35
+ block.call
36
+ end
37
+
38
+ # @param [BenchmarkDriver::Metrics] metrics
39
+ def report(metrics)
40
+ $stdout.print '.'
41
+ if @with_benchmark
42
+ @metrics_by_job[@current_job][:benchmark] << metrics
43
+ else
44
+ @metrics_by_job[@current_job][:warmup] << metrics
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def save_record
51
+ jobs = @benchmark_metrics
52
+ yaml = {
53
+ 'type' => 'recorded',
54
+ 'metrics_by_job' => @metrics_by_job,
55
+ 'metrics_type' => @metrics_type,
56
+ }.to_yaml
57
+ File.write('benchmark_driver.record.yml', yaml)
58
+ end
59
+ end
@@ -1,17 +1,17 @@
1
1
  class BenchmarkDriver::Output::Simple
2
2
  NAME_LENGTH = 8
3
3
 
4
+ # @param [BenchmarkDriver::Metrics::Type] metrics_type
5
+ attr_writer :metrics_type
6
+
4
7
  # @param [Array<BenchmarkDriver::*::Job>] jobs
5
8
  # @param [Array<BenchmarkDriver::Config::Executable>] executables
6
- # @param [BenchmarkDriver::Metrics::Type] metrics_type
7
- def initialize(jobs:, executables:, metrics_type:)
9
+ def initialize(jobs:, executables:)
8
10
  @jobs = jobs
9
11
  @executables = executables
10
- @metrics_type = metrics_type
11
12
  @name_length = jobs.map { |j| j.name.size }.max
12
13
  end
13
14
 
14
- # @param [BenchmarkDriver::Metrics] metrics
15
15
  def with_warmup(&block)
16
16
  without_stdout_buffering do
17
17
  $stdout.print 'warming up'
@@ -21,7 +21,6 @@ class BenchmarkDriver::Output::Simple
21
21
  $stdout.puts
22
22
  end
23
23
 
24
- # @param [BenchmarkDriver::Metrics] metrics
25
24
  def with_benchmark(&block)
26
25
  @with_benchmark = true
27
26
  without_stdout_buffering do
@@ -3,6 +3,7 @@ module BenchmarkDriver
3
3
  require 'benchmark_driver/runner/ips'
4
4
  require 'benchmark_driver/runner/memory'
5
5
  require 'benchmark_driver/runner/once'
6
+ require 'benchmark_driver/runner/recorded'
6
7
  require 'benchmark_driver/runner/time'
7
8
  end
8
9
 
@@ -29,7 +30,6 @@ module BenchmarkDriver
29
30
  output = Output.find(config.output_type).new(
30
31
  jobs: jobs,
31
32
  executables: config.executables,
32
- metrics_type: runner::MetricsType,
33
33
  )
34
34
  runner.new(config: runner_config, output: output).run(jobs)
35
35
  end
@@ -11,8 +11,8 @@ class BenchmarkDriver::Runner::Ips
11
11
  Job = Class.new(BenchmarkDriver::DefaultJob)
12
12
  # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
13
13
  JobParser = BenchmarkDriver::DefaultJobParser.for(Job)
14
- # Passed to `output` by `BenchmarkDriver::Runner.run`
15
- MetricsType = BenchmarkDriver::Metrics::Type.new(unit: 'i/s')
14
+
15
+ METRICS_TYPE = BenchmarkDriver::Metrics::Type.new(unit: 'i/s')
16
16
 
17
17
  # @param [BenchmarkDriver::Config::RunnerConfig] config
18
18
  # @param [BenchmarkDriver::Output::*] output
@@ -24,6 +24,8 @@ class BenchmarkDriver::Runner::Ips
24
24
  # This method is dynamically called by `BenchmarkDriver::JobRunner.run`
25
25
  # @param [Array<BenchmarkDriver::Default::Job>] jobs
26
26
  def run(jobs)
27
+ set_metrics_type
28
+
27
29
  if jobs.any? { |job| job.loop_count.nil? }
28
30
  @output.with_warmup do
29
31
  jobs = jobs.map do |job|
@@ -123,6 +125,11 @@ class BenchmarkDriver::Runner::Ips
123
125
  )
124
126
  end
125
127
 
128
+ # This method is overridden by BenchmarkDriver::Runner::Time
129
+ def set_metrics_type
130
+ @output.metrics_type = METRICS_TYPE
131
+ end
132
+
126
133
  def with_script(script)
127
134
  if @config.verbose >= 2
128
135
  sep = '-' * 30
@@ -11,8 +11,8 @@ class BenchmarkDriver::Runner::Memory
11
11
  Job = Class.new(BenchmarkDriver::DefaultJob)
12
12
  # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
13
13
  JobParser = BenchmarkDriver::DefaultJobParser.for(Job)
14
- # Passed to `output` by `BenchmarkDriver::Runner.run`
15
- MetricsType = BenchmarkDriver::Metrics::Type.new(unit: 'bytes', larger_better: false, worse_word: 'larger')
14
+
15
+ METRICS_TYPE = BenchmarkDriver::Metrics::Type.new(unit: 'bytes', larger_better: false, worse_word: 'larger')
16
16
 
17
17
  # @param [BenchmarkDriver::Config::RunnerConfig] config
18
18
  # @param [BenchmarkDriver::Output::*] output
@@ -29,6 +29,8 @@ class BenchmarkDriver::Runner::Memory
29
29
  raise "memory output is not supported for '#{Etc.uname[:sysname]}' for now"
30
30
  end
31
31
 
32
+ @output.metrics_type = METRICS_TYPE
33
+
32
34
  if jobs.any? { |job| job.loop_count.nil? }
33
35
  jobs = jobs.map do |job|
34
36
  job.loop_count ? job : Job.new(job.to_h.merge(loop_count: 1))
@@ -11,8 +11,8 @@ class BenchmarkDriver::Runner::Once
11
11
  Job = Class.new(BenchmarkDriver::DefaultJob)
12
12
  # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
13
13
  JobParser = BenchmarkDriver::DefaultJobParser.for(Job)
14
- # Passed to `output` by `BenchmarkDriver::Runner.run`
15
- MetricsType = BenchmarkDriver::Metrics::Type.new(unit: 'i/s')
14
+
15
+ METRICS_TYPE = BenchmarkDriver::Metrics::Type.new(unit: 'i/s')
16
16
 
17
17
  # @param [BenchmarkDriver::Config::RunnerConfig] config
18
18
  # @param [BenchmarkDriver::Output::*] output
@@ -24,6 +24,8 @@ class BenchmarkDriver::Runner::Once
24
24
  # This method is dynamically called by `BenchmarkDriver::JobRunner.run`
25
25
  # @param [Array<BenchmarkDriver::Default::Job>] jobs
26
26
  def run(jobs)
27
+ @output.metrics_type = METRICS_TYPE
28
+
27
29
  jobs = jobs.map do |job|
28
30
  Job.new(job.to_h.merge(loop_count: 1)) # to show this on output
29
31
  end
@@ -0,0 +1,61 @@
1
+ require 'benchmark_driver/struct'
2
+ require 'benchmark_driver/metrics'
3
+ require 'tempfile'
4
+ require 'shellwords'
5
+
6
+ # Run only once, for testing
7
+ class BenchmarkDriver::Runner::Recorded
8
+ # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job"
9
+ Job = ::BenchmarkDriver::Struct.new(
10
+ :name, # @param [String] name - This is mandatory for all runner
11
+ :job, # @param [BenchmarkDriver::Runner::*::Job]
12
+ :warmup_metrics, # @param [Hash]
13
+ :benchmark_metrics, # @param [Hash]
14
+ :metrics_type, # @param [BenchmarkDriver::Metrics::Type]
15
+ )
16
+ # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
17
+ class << JobParser = Module.new
18
+ # @param [Hash] metrics_by_job
19
+ # @param [BenchmarkDriver::Metrics::Type] metrics_type
20
+ def parse(metrics_by_job:, metrics_type:)
21
+ metrics_by_job.map do |job, metrics_hash|
22
+ Job.new(
23
+ name: job.name,
24
+ job: job,
25
+ warmup_metrics: metrics_hash.fetch(:warmup, []),
26
+ benchmark_metrics: metrics_hash.fetch(:benchmark),
27
+ metrics_type: metrics_type,
28
+ )
29
+ end
30
+ end
31
+ end
32
+
33
+ # @param [BenchmarkDriver::Config::RunnerConfig] config
34
+ # @param [BenchmarkDriver::Output::*] output
35
+ def initialize(config:, output:)
36
+ @config = config
37
+ @output = output
38
+ end
39
+
40
+ # This method is dynamically called by `BenchmarkDriver::JobRunner.run`
41
+ # @param [Array<BenchmarkDriver::Default::Job>] jobs
42
+ def run(records)
43
+ @output.metrics_type = records.first.metrics_type
44
+
45
+ records.each do |record|
46
+ unless record.warmup_metrics.empty?
47
+ # TODO:
48
+ end
49
+ end
50
+
51
+ @output.with_benchmark do
52
+ records.each do |record|
53
+ @output.with_job(record.job) do
54
+ record.benchmark_metrics.each do |metrics|
55
+ @output.report(metrics)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -5,8 +5,13 @@ class BenchmarkDriver::Runner::Time < BenchmarkDriver::Runner::Ips
5
5
  Job = Class.new(BenchmarkDriver::DefaultJob)
6
6
  # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
7
7
  JobParser = BenchmarkDriver::DefaultJobParser.for(Job)
8
- # Passed to `output` by `BenchmarkDriver::Runner.run`
9
- MetricsType = BenchmarkDriver::Metrics::Type.new(unit: 's')
8
+
9
+ METRICS_TYPE = BenchmarkDriver::Metrics::Type.new(unit: 's')
10
+
11
+ # Overriding BenchmarkDriver::Runner::Ips#set_metrics_type
12
+ def set_metrics_type
13
+ @output.metrics_type = METRICS_TYPE
14
+ end
10
15
 
11
16
  # Overriding BenchmarkDriver::Runner::Ips#build_metrics
12
17
  def build_metrics(duration:, executable:, loop_count:)
@@ -1,3 +1,3 @@
1
1
  module BenchmarkDriver
2
- VERSION = '0.9.2'
2
+ VERSION = '0.10.0'
3
3
  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.9.2
4
+ version: 0.10.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-02-24 00:00:00.000000000 Z
11
+ date: 2018-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -77,6 +77,7 @@ files:
77
77
  - lib/benchmark_driver/output.rb
78
78
  - lib/benchmark_driver/output/compare.rb
79
79
  - lib/benchmark_driver/output/markdown.rb
80
+ - lib/benchmark_driver/output/record.rb
80
81
  - lib/benchmark_driver/output/simple.rb
81
82
  - lib/benchmark_driver/rbenv.rb
82
83
  - lib/benchmark_driver/ruby_interface.rb
@@ -84,6 +85,7 @@ files:
84
85
  - lib/benchmark_driver/runner/ips.rb
85
86
  - lib/benchmark_driver/runner/memory.rb
86
87
  - lib/benchmark_driver/runner/once.rb
88
+ - lib/benchmark_driver/runner/recorded.rb
87
89
  - lib/benchmark_driver/runner/time.rb
88
90
  - lib/benchmark_driver/struct.rb
89
91
  - lib/benchmark_driver/version.rb