lib/benchmark_driver/output/compare.rb in benchmark_driver-0.10.16 vs lib/benchmark_driver/output/compare.rb in benchmark_driver-0.11.0

- old
+ new

@@ -1,17 +1,18 @@ # Compare output like benchmark-ips class BenchmarkDriver::Output::Compare NAME_LENGTH = 20 - # @param [BenchmarkDriver::Metrics::Type] metrics_type - attr_writer :metrics_type + # @param [Array<BenchmarkDriver::Metric>] metrics + attr_writer :metrics - # @param [Array<BenchmarkDriver::*::Job>] jobs - # @param [Array<BenchmarkDriver::Config::Executable>] executables - def initialize(jobs:, executables:) - @jobs = jobs - @executables = executables + # @param [Array<String>] job_names + # @param [Array<String>] context_names + def initialize(job_names:, context_names:) + @job_names = job_names + @context_names = context_names + @name_length = [job_names.map(&:length).max, NAME_LENGTH].max end def with_warmup(&block) without_stdout_buffering do $stdout.puts 'Warming up --------------------------------------' @@ -19,76 +20,87 @@ block.call end end def with_benchmark(&block) - @metrics_by_job = Hash.new { |h, k| h[k] = [] } + @job_context_values = Hash.new do |h1, k1| + h1[k1] = Hash.new { |h2, k2| h2[k2] = [] } + end without_stdout_buffering do $stdout.puts 'Calculating -------------------------------------' - if @executables.size > 1 - $stdout.print(' ' * NAME_LENGTH) - @executables.each do |executable| - $stdout.print(' %10s ' % executable.name) + if @context_names.size > 1 + $stdout.print(' ' * @name_length) + @context_names.each do |context_name| + $stdout.print(' %10s ' % context_name) end $stdout.puts end block.call end ensure - if @executables.size > 1 + if @context_names.size > 1 compare_executables - elsif @jobs.size > 1 + elsif @job_names.size > 1 compare_jobs end end - # @param [BenchmarkDriver::*::Job] job + # @param [BenchmarkDriver::Job] job def with_job(job, &block) - if job.name.length > NAME_LENGTH - $stdout.puts(job.name) + name = job.name + if name.length > @name_length + $stdout.puts(name) else - $stdout.print("%#{NAME_LENGTH}s" % job.name) + $stdout.print("%#{@name_length}s" % name) end - @current_job = job - @job_metrics = [] + @job = name + @job_contexts = [] block.call ensure - $stdout.print(@metrics_type.unit) - if job.respond_to?(:loop_count) && job.loop_count - $stdout.print(" - #{humanize(job.loop_count)} times") - if @job_metrics.all? { |metrics| metrics.duration } + $stdout.print(@metrics.first.unit) + loop_count = @job_contexts.first.loop_count + if loop_count && @job_contexts.all? { |c| c.loop_count == loop_count } + $stdout.print(" - #{humanize(loop_count)} times") + if @job_contexts.all? { |context| !context.duration.nil? } $stdout.print(" in") show_durations end end $stdout.puts end - # @param [BenchmarkDriver::Metrics] metrics - def report(metrics) - if defined?(@metrics_by_job) - @metrics_by_job[@current_job] << metrics + # @param [BenchmarkDriver::Context] context + def with_context(context, &block) + @context = context + @job_contexts << context + block.call + end + + # @param [Float] value + # @param [BenchmarkDriver::Metric] metic + def report(value:, metric:) + if defined?(@job_context_values) + @job_context_values[@job][@context] << value end - @job_metrics << metrics - $stdout.print("#{humanize(metrics.value, [10, metrics.executable.name.length].max)} ") + $stdout.print("#{humanize(value, [10, @context.name.length].max)} ") end private def show_durations - @job_metrics.each do |metrics| - $stdout.print(' %3.6fs' % metrics.duration) + @job_contexts.each do |context| + $stdout.print(' %3.6fs' % context.duration) end # Show pretty seconds / clocks too. As it takes long width, it's shown only with a single executable. - if @job_metrics.size == 1 - metrics = @job_metrics.first - sec = metrics.duration - iter = @current_job.loop_count + if @job_contexts.size == 1 + context = @job_contexts.first + sec = context.duration + iter = context.loop_count if File.exist?('/proc/cpuinfo') && (clks = estimate_clock(sec, iter)) < 1_000 $stdout.print(" (#{pretty_sec(sec, iter)}/i, #{clks}clocks/i)") else $stdout.print(" (#{pretty_sec(sec, iter)}/i)") end @@ -146,52 +158,56 @@ Integer(r/(1/hz)) end def compare_jobs $stdout.puts "\nComparison:" - results = @metrics_by_job.map { |job, metrics| Result.new(job: job, metrics: metrics.first) } + results = @job_context_values.flat_map do |job, context_values| + context_values.map { |context, values| Result.new(job: job, value: values.first, executable: context.executable) } + end show_results(results, show_executable: false) end def compare_executables $stdout.puts "\nComparison:" - @metrics_by_job.each do |job, metrics| - $stdout.puts("%#{NAME_LENGTH + 2 + 11}s" % job.name) - results = metrics.map { |metrics| Result.new(job: job, metrics: metrics) } + @job_context_values.each do |job, context_values| + $stdout.puts("%#{@name_length + 2 + 11}s" % job) + results = context_values.flat_map do |context, values| + values.map { |value| Result.new(job: job, value: value, executable: context.executable) } + end show_results(results, show_executable: true) end end # @param [Array<BenchmarkDriver::Output::Compare::Result>] results # @param [TrueClass,FalseClass] show_executable def show_results(results, show_executable:) results = results.sort_by do |result| - if @metrics_type.larger_better - -result.metrics.value + if @metrics.first.larger_better + -result.value else - result.metrics.value + result.value end end first = results.first results.each do |result| if result != first - if @metrics_type.larger_better - ratio = (first.metrics.value / result.metrics.value) + if @metrics.first.larger_better + ratio = (first.value / result.value) else - ratio = (result.metrics.value / first.metrics.value) + ratio = (result.value / first.value) end - slower = "- %.2fx #{@metrics_type.worse_word}" % ratio + slower = "- %.2fx #{@metrics.first.worse_word}" % ratio end if show_executable - name = result.metrics.executable.name + name = result.executable.name else - name = result.job.name + name = result.job end - $stdout.puts("%#{NAME_LENGTH}s: %11.1f %s #{slower}" % [name, result.metrics.value, @metrics_type.unit]) + $stdout.puts("%#{@name_length}s: %11.1f %s #{slower}" % [name, result.value, @metrics.first.unit]) end $stdout.puts end - Result = ::BenchmarkDriver::Struct.new(:job, :metrics) + Result = ::BenchmarkDriver::Struct.new(:job, :value, :executable) end