class Benchmark::IPS::Job
Benchmark
jobs.
Benchmark
jobs.
Constants
- MAX_TIME_SKEW
The percentage of the expected runtime to allow before reporting a weird runtime
- MICROSECONDS_PER_100MS
Microseconds per 100 millisecond.
- MICROSECONDS_PER_SECOND
Microseconds per second.
Attributes
Determining whether to run comparison utility. @return [Boolean] true if needs to run compare.
Confidence. @return [Integer]
Report
object containing information about the run. @return [Report] the report object.
Determining whether to hold results between Ruby invocations @return [Boolean]
Warmup and calculation iterations. @return [Integer]
Two-element arrays, consisting of label and block pairs. @return [Array<Entry>] list of entries
Statistics model. @return [Object]
Calculation time setter and getter (in seconds). @return [Integer]
Storing Iterations in time period. @return [Hash]
Warmup time setter and getter (in seconds). @return [Integer]
Public Class Methods
Instantiate the Benchmark::IPS::Job
. @option opts [Benchmark::Suite] (nil) :suite Specify Benchmark::Suite. @option opts [Boolean] (false) :quiet Suppress the printing of information.
# File lib/benchmark/ips/job.rb, line 56 def initialize opts={} @suite = opts[:suite] || nil @stdout = opts[:quiet] ? nil : StdoutReport.new @list = [] @compare = false @json_path = false @held_path = nil @held_results = nil @timing = {} @full_report = Report.new # Default warmup and calculation time in seconds. @warmup = 2 @time = 5 @iterations = 1 # Default statistical model @stats = :sd @confidence = 95 end
Public Instance Methods
Set @compare to true.
# File lib/benchmark/ips/job.rb, line 98 def compare! @compare = true end
Return true if job needs to be compared. @return [Boolean] Need to compare?
# File lib/benchmark/ips/job.rb, line 93 def compare? @compare end
Job
configuration options, set +@warmup+ and +@time+. @option opts [Integer] :warmup Warmup time. @option opts [Integer] :time Calculation time. @option iterations [Integer] :time Warmup and calculation iterations.
# File lib/benchmark/ips/job.rb, line 82 def config opts @warmup = opts[:warmup] if opts[:warmup] @time = opts[:time] if opts[:time] @suite = opts[:suite] if opts[:suite] @iterations = opts[:iterations] if opts[:iterations] @stats = opts[:stats] if opts[:stats] @confidence = opts[:confidence] if opts[:confidence] end
Create report by add entry to +@full_report+. @param label [String] Report
item label. @param measured_us [Integer] Measured time in microsecond. @param iter [Integer] Iterations. @param samples [Array<Float>] Sampled iterations per second. @param cycles [Integer] Number of Cycles. @return [Report::Entry] Entry
with data.
# File lib/benchmark/ips/job.rb, line 344 def create_report(label, measured_us, iter, samples, cycles) @full_report.add_entry label, measured_us, iter, samples, cycles end
# File lib/benchmark/ips/job.rb, line 316 def create_stats(samples) case @stats when :sd Stats::SD.new(samples) when :bootstrap Stats::Bootstrap.new(samples, @confidence) else raise "unknown stats #{@stats}" end end
Calculate the cycles needed to run for approx 100ms, given the number of iterations to run the given time. @param [Float] time_msec Each iteration's time in ms. @param [Integer] iters Iterations. @return [Integer] Cycles per 100ms.
# File lib/benchmark/ips/job.rb, line 148 def cycles_per_100ms time_msec, iters cycles = ((MICROSECONDS_PER_100MS / time_msec) * iters).to_i cycles <= 0 ? 1 : cycles end
Generate json from +@full_report+.
# File lib/benchmark/ips/job.rb, line 333 def generate_json @full_report.generate_json @json_path if json? end
# File lib/benchmark/ips/job.rb, line 170 def held_results? File.exist?(@held_path) end
Set @hold to true.
# File lib/benchmark/ips/job.rb, line 109 def hold!(held_path) @held_path = held_path end
Return true if results are held while multiple Ruby invocations @return [Boolean] Need to hold results between multiple Ruby invocations?
# File lib/benchmark/ips/job.rb, line 104 def hold? !!@held_path end
Registers the given label and block pair in the job list. @param label [String] Label of benchmarked code. @param str [String] Code to be benchmarked. @param blk [Proc] Code to be benchmarked. @raise [ArgumentError] Raises if str and blk are both present. @raise [ArgumentError] Raises if str and blk are both absent.
# File lib/benchmark/ips/job.rb, line 130 def item(label="", str=nil, &blk) # :yield: if blk and str raise ArgumentError, "specify a block and a str, but not both" end action = str || blk raise ArgumentError, "no block or string" unless action @list.push Entry.new(label, action) self end
Calculate the interations per second given the number of cycles run and the time in microseconds that elapsed. @param [Integer] cycles Cycles. @param [Integer] time_us
Time in microsecond. @return [Float] Iteration per second.
# File lib/benchmark/ips/job.rb, line 166 def iterations_per_sec cycles, time_us MICROSECONDS_PER_SECOND * (cycles.to_f / time_us.to_f) end
Set @json_path to given path, defaults to “data.json”.
# File lib/benchmark/ips/job.rb, line 120 def json!(path="data.json") @json_path = path end
Return true if job needs to generate json. @return [Boolean] Need to generate json?
# File lib/benchmark/ips/job.rb, line 115 def json? !!@json_path end
# File lib/benchmark/ips/job.rb, line 174 def load_held_results require "json" @held_results = Hash[File.open(@held_path).map { |line| result = JSON.parse(line) [result['item'], result] }] end
# File lib/benchmark/ips/job.rb, line 182 def run @stdout.start_warming if @stdout @iterations.times do run_warmup end @stdout.start_running if @stdout held = nil @iterations.times do |n| held = run_benchmark end @stdout.footer if @stdout if held puts puts 'Pausing here -- run Ruby again to measure the next benchmark...' end end
Run calculation.
# File lib/benchmark/ips/job.rb, line 238 def run_benchmark @list.each do |item| if hold? && @held_results && @held_results.key?(item.label) result = @held_results[item.label] create_report(item.label, result['measured_us'], result['iter'], create_stats(result['samples']), result['cycles']) next end @suite.running item.label, @time if @suite @stdout.running item.label, @time if @stdout Timing.clean_env iter = 0 measurements_us = [] # Running this number of cycles should take around 100ms. cycles = @timing[item] target = Timing.add_second Timing.now, @time while (before = Timing.now) < target item.call_times cycles after = Timing.now # If for some reason the timing said this took no time (O_o) # then ignore the iteration entirely and start another. iter_us = Timing.time_us before, after next if iter_us <= 0.0 iter += cycles measurements_us << iter_us end final_time = before measured_us = measurements_us.inject(:+) samples = measurements_us.map { |time_us| iterations_per_sec cycles, time_us } rep = create_report(item.label, measured_us, iter, create_stats(samples), cycles) if (final_time - target).abs >= (@time.to_f * MAX_TIME_SKEW) rep.show_total_time! end @stdout.add_report rep, caller(1).first if @stdout @suite.add_report rep, caller(1).first if @suite if hold? && item != @list.last File.open @held_path, "a" do |f| require "json" f.write JSON.generate({ :item => item.label, :measured_us => measured_us, :iter => iter, :samples => samples, :cycles => cycles }) f.write "\n" end return true end end if hold? && @full_report.entries.size == @list.size File.delete @held_path if File.exist?(@held_path) end false end
Run comparison of entries in +@full_report+.
# File lib/benchmark/ips/job.rb, line 328 def run_comparison @full_report.run_comparison if compare? end
Run warmup.
# File lib/benchmark/ips/job.rb, line 205 def run_warmup @list.each do |item| next if hold? && @held_results && @held_results.key?(item.label) @suite.warming item.label, @warmup if @suite @stdout.warming item.label, @warmup if @stdout Timing.clean_env before = Timing.now target = Timing.add_second before, @warmup warmup_iter = 0 while Timing.now < target item.call_times(1) warmup_iter += 1 end after = Timing.now warmup_time_us = Timing.time_us(before, after) @timing[item] = cycles_per_100ms warmup_time_us, warmup_iter @stdout.warmup_stats warmup_time_us, @timing[item] if @stdout @suite.warmup_stats warmup_time_us, @timing[item] if @suite break if hold? end end
Calculate the time difference of before and after in microseconds. @param [Time] before time. @param [Time] after time. @return [Float] Time difference of before and after.
# File lib/benchmark/ips/job.rb, line 157 def time_us before, after (after.to_f - before.to_f) * MICROSECONDS_PER_SECOND end