benchmark_driver 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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