From f328fe40b3bb22ef60713cfc707ba9716ade6cd6 Mon Sep 17 00:00:00 2001 From: k0kubun Date: Tue, 10 Jul 2018 15:01:27 +0000 Subject: benchmark_driver/runner: add runners for metrics supported by legacy benchmark/driver.rb. benchmark/README.md: document them common.mk: update benchmark_driver to correct 0.0 output and to fix spacing format of `-o simple` and `-o markdown`. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63933 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- benchmark/lib/benchmark_driver/runner/cstime.rb | 22 ++++ benchmark/lib/benchmark_driver/runner/cutime.rb | 22 ++++ benchmark/lib/benchmark_driver/runner/stime.rb | 22 ++++ benchmark/lib/benchmark_driver/runner/total.rb | 137 ++++++++++++++++++++++++ benchmark/lib/benchmark_driver/runner/utime.rb | 22 ++++ 5 files changed, 225 insertions(+) create mode 100644 benchmark/lib/benchmark_driver/runner/cstime.rb create mode 100644 benchmark/lib/benchmark_driver/runner/cutime.rb create mode 100644 benchmark/lib/benchmark_driver/runner/stime.rb create mode 100644 benchmark/lib/benchmark_driver/runner/total.rb create mode 100644 benchmark/lib/benchmark_driver/runner/utime.rb (limited to 'benchmark/lib') diff --git a/benchmark/lib/benchmark_driver/runner/cstime.rb b/benchmark/lib/benchmark_driver/runner/cstime.rb new file mode 100644 index 0000000000..3c3453e527 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/cstime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Cstime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'cstime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :cstime + end +end diff --git a/benchmark/lib/benchmark_driver/runner/cutime.rb b/benchmark/lib/benchmark_driver/runner/cutime.rb new file mode 100644 index 0000000000..e139962ef2 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/cutime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Cutime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'cutime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :cutime + end +end diff --git a/benchmark/lib/benchmark_driver/runner/stime.rb b/benchmark/lib/benchmark_driver/runner/stime.rb new file mode 100644 index 0000000000..4577fb0bf8 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/stime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Stime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'stime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :stime + end +end diff --git a/benchmark/lib/benchmark_driver/runner/total.rb b/benchmark/lib/benchmark_driver/runner/total.rb new file mode 100644 index 0000000000..64dc14f84e --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/total.rb @@ -0,0 +1,137 @@ +require 'benchmark_driver/struct' +require 'benchmark_driver/metric' +require 'benchmark_driver/default_job' +require 'benchmark_driver/default_job_parser' +require 'tempfile' + +class BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'Total time', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + # @param [BenchmarkDriver::Config::RunnerConfig] config + # @param [BenchmarkDriver::Output] output + # @param [BenchmarkDriver::Context] contexts + def initialize(config:, output:, contexts:) + @config = config + @output = output + @contexts = contexts + end + + # This method is dynamically called by `BenchmarkDriver::JobRunner.run` + # @param [Array] jobs + def run(jobs) + if jobs.any? { |job| job.loop_count.nil? } + raise 'missing loop_count is not supported in Ruby repository' + end + + @output.with_benchmark do + jobs.each do |job| + @output.with_job(name: job.name) do + job.runnable_contexts(@contexts).each do |context| + duration = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: false) do + run_benchmark(job, context: context) + end + @output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do + @output.report(values: { metric => duration }, duration: duration, loop_count: job.loop_count) + end + end + end + end + end + end + + private + + # @param [BenchmarkDriver::Runner::Ips::Job] job - loop_count is not nil + # @param [BenchmarkDriver::Context] context + # @return [BenchmarkDriver::Metrics] + def run_benchmark(job, context:) + benchmark = BenchmarkScript.new( + preludes: [context.prelude, job.prelude], + script: job.script, + teardown: job.teardown, + loop_count: job.loop_count, + ) + + Tempfile.open(['benchmark_driver-', '.rb']) do |f| + with_script(benchmark.render(result: f.path, target: target)) do |path| + IO.popen([*context.executable.command, path], &:read) # TODO: print stdout if verbose=2 + if $?.success? + Float(f.read) + else + BenchmarkDriver::Result::ERROR + end + end + end + end + + # This method is overridden by some subclasses + def metric + METRIC + end + + # This method is overridden by some subclasses + def target + :total + end + + def with_script(script) + if @config.verbose >= 2 + sep = '-' * 30 + $stdout.puts "\n\n#{sep}[Script begin]#{sep}\n#{script}#{sep}[Script end]#{sep}\n\n" + end + + Tempfile.open(['benchmark_driver-', '.rb']) do |f| + f.puts script + f.close + return yield(f.path) + end + end + + # @param [String] prelude + # @param [String] script + # @param [String] teardown + # @param [Integer] loop_count + BenchmarkScript = ::BenchmarkDriver::Struct.new(:preludes, :script, :teardown, :loop_count) do + # @param [String] result - A file to write result + def render(result:, target:) + prelude = preludes.reject(&:nil?).reject(&:empty?).join("\n") + <<-RUBY +#{prelude} + +require 'benchmark' +__bmdv_result = Benchmark.measure { + #{while_loop(script, loop_count)} +} + +#{teardown} + +File.write(#{result.dump}, __bmdv_result.#{target}) + RUBY + end + + private + + def while_loop(content, times) + if !times.is_a?(Integer) || times <= 0 + raise ArgumentError.new("Unexpected times: #{times.inspect}") + elsif times == 1 + return content + end + + # TODO: execute in batch + <<-RUBY +__bmdv_i = 0 +while __bmdv_i < #{times} + #{content} + __bmdv_i += 1 +end + RUBY + end + end + private_constant :BenchmarkScript +end diff --git a/benchmark/lib/benchmark_driver/runner/utime.rb b/benchmark/lib/benchmark_driver/runner/utime.rb new file mode 100644 index 0000000000..b61d83a188 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/utime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Utime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'utime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :utime + end +end -- cgit v1.2.3