Class: Benchmark::IPS::Job

Inherits:
Object
  • Object
show all
Defined in:
lib/benchmark/ips/job.rb

Overview

Benchmark jobs.

Defined Under Namespace

Classes: Entry

Constant Summary collapse

MICROSECONDS_PER_100MS =

Microseconds per 100 millisecond.

100_000
MICROSECONDS_PER_SECOND =

Microseconds per second.

1_000_000
MAX_TIME_SKEW =

The percentage of the expected runtime to allow before reporting a weird runtime

0.05

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Job

Instantiate the Benchmark::IPS::Job.

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • (nil) (Benchmark::Suite)

    :suite Specify Benchmark::Suite.

  • (false) (Boolean)

    :quiet Suppress the printing of information.



124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/benchmark/ips/job.rb', line 124

def initialize opts={}
  @suite = opts[:suite] || nil
  @quiet = opts[:quiet] || false
  @list = []
  @compare = false

  @timing = {}
  @full_report = Report.new

  # Default warmup and calculation time in seconds.
  @warmup = 2
  @time = 5
end

Instance Attribute Details

#compareBoolean (readonly)

Determining whether to run comparison utility.

Returns:

  • (Boolean)

    true if needs to run compare.



103
104
105
# File 'lib/benchmark/ips/job.rb', line 103

def compare
  @compare
end

#full_reportReport (readonly)

Report object containing information about the run.

Returns:

  • (Report)

    the report object.



107
108
109
# File 'lib/benchmark/ips/job.rb', line 107

def full_report
  @full_report
end

#listArray<Entry> (readonly)

Two-element arrays, consisting of label and block pairs.

Returns:

  • (Array<Entry>)

    list of entries



99
100
101
# File 'lib/benchmark/ips/job.rb', line 99

def list
  @list
end

#timeInteger

Calculation time setter and getter (in seconds).

Returns:

  • (Integer)


119
120
121
# File 'lib/benchmark/ips/job.rb', line 119

def time
  @time
end

#timingHash (readonly)

Storing Iterations in time period.

Returns:

  • (Hash)


111
112
113
# File 'lib/benchmark/ips/job.rb', line 111

def timing
  @timing
end

#warmupInteger

Warmup time setter and getter (in seconds).

Returns:

  • (Integer)


115
116
117
# File 'lib/benchmark/ips/job.rb', line 115

def warmup
  @warmup
end

Instance Method Details

#compare!Object

Set @compare to true.



153
154
155
# File 'lib/benchmark/ips/job.rb', line 153

def compare!
  @compare = true
end

#compare?Boolean

Return true if job needs to be compared.

Returns:

  • (Boolean)

    Need to compare?



148
149
150
# File 'lib/benchmark/ips/job.rb', line 148

def compare?
  @compare
end

#config(opts) ⇒ Object

Job configuration options, set @warmup and @time.

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :warmup (Integer)

    Warmup time.

  • :time (Integer)

    Calculation time.



141
142
143
144
# File 'lib/benchmark/ips/job.rb', line 141

def config opts
  @warmup = opts[:warmup] if opts[:warmup]
  @time = opts[:time] if opts[:time]
end

#create_report(item, measured_us, iter, avg_ips, sd_ips, cycles) ⇒ Object

Create report by add entry to @full_report.

Parameters:

  • item (Benchmark::IPS::Job::Entry)

    Report item.

  • measured_us (Integer)

    Measured time in microsecond.

  • iter (Integer)

    Iterations.

  • avg_ips (Float)

    Average iterations per second.

  • sd_ips (Float)

    Standard deviation iterations per second.

  • cycles (Integer)

    Number of Cycles.



312
313
314
# File 'lib/benchmark/ips/job.rb', line 312

def create_report(item, measured_us, iter, avg_ips, sd_ips, cycles)
  @full_report.add_entry item.label, measured_us, iter, avg_ips, sd_ips, cycles
end

#cycles_per_100ms(time_msec, iters) ⇒ Integer

Calculate the cycles needed to run for approx 100ms, given the number of iterations to run the given time.

Parameters:

  • time_msec (Float)

    Each iteration’s time in ms.

  • iters (Integer)

    Iterations.

Returns:

  • (Integer)

    Cycles per 100ms.



181
182
183
184
185
# File 'lib/benchmark/ips/job.rb', line 181

def cycles_per_100ms time_msec, iters
  cycles = ((MICROSECONDS_PER_100MS / time_msec) * iters).to_i
  cycles = 1 if cycles <= 0
  cycles
end

#item(label = "", str = nil, &blk) ⇒ Object Also known as: report

Registers the given label and block pair in the job list.

Parameters:

  • label (String) (defaults to: "")

    Label of benchmarked code.

  • str (String) (defaults to: nil)

    Code to be benchamrked.

  • blk (Proc)

    Code to be benchamrked.

Raises:

  • (ArgumentError)

    Raises if str and blk are both present.

  • (ArgumentError)

    Raises if str and blk are both absent.



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/benchmark/ips/job.rb', line 163

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

#iterations_per_sec(cycles, time_us) ⇒ Float

Calculate the interations per second given the number of cycles run and the time in microseconds that elapsed.

Parameters:

  • cycles (Integer)

    Cycles.

  • time_us (Integer)

    Time in microsecond.

Returns:

  • (Float)

    Iteration per second.



200
201
202
# File 'lib/benchmark/ips/job.rb', line 200

def iterations_per_sec cycles, time_us
  MICROSECONDS_PER_SECOND * (cycles.to_f / time_us.to_f)
end

#runObject

Run calculation.



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/benchmark/ips/job.rb', line 243

def run
  @list.each do |item|
    @suite.running item.label, @time if @suite

    unless @quiet
      $stdout.print item.label_rjust
    end

    Timing.clean_env

    iter = 0

    target = Time.now + @time

    measurements_us = []

    # Running this number of cycles should take around 100ms.
    cycles = @timing[item]

    while Time.now < target
      before = Time.now
      item.call_times cycles
      after = Time.now

      # If for some reason the timing said this took no time (O_o)
      # then ignore the iteration entirely and start another.
      iter_us = time_us before, after
      next if iter_us <= 0.0

      iter += cycles

      measurements_us << iter_us
    end

    final_time = Time.now

    measured_us = measurements_us.inject(0) { |a,i| a + i }

    all_ips = measurements_us.map { |time_us|
      iterations_per_sec cycles, time_us
    }

    avg_ips = Timing.mean(all_ips)
    sd_ips =  Timing.stddev(all_ips).round

    rep = create_report(item, measured_us, iter, avg_ips, sd_ips, cycles)

    if (final_time - target).abs >= (@time.to_f * MAX_TIME_SKEW)
      rep.show_total_time!
    end

    $stdout.puts " #{rep.body}" unless @quiet

    @suite.add_report rep, caller(1).first if @suite
  end
end

#run_comparisonObject

Run comparison of entries in @full_report.



301
302
303
# File 'lib/benchmark/ips/job.rb', line 301

def run_comparison
  @full_report.run_comparison
end

#run_warmupObject

Run warmup.



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/benchmark/ips/job.rb', line 205

def run_warmup
  @list.each do |item|
    @suite.warming item.label, @warmup if @suite

    unless @quiet
      $stdout.printf item.label_rjust
    end

    Timing.clean_env

    before = Time.now
    target = Time.now + @warmup

    warmup_iter = 0

    while Time.now < target
      item.call_times(1)
      warmup_iter += 1
    end

    after = Time.now

    warmup_time_us = time_us before, after

    @timing[item] = cycles_per_100ms warmup_time_us, warmup_iter

    case Benchmark::IPS.options[:format]
    when :human
      $stdout.printf "%s i/100ms\n", Helpers.scale(@timing[item]) unless @quiet
    else
      $stdout.printf "%10d i/100ms\n", @timing[item] unless @quiet
    end

    @suite.warmup_stats warmup_time_us, @timing[item] if @suite
  end
end

#time_us(before, after) ⇒ Float

Calculate the time difference of before and after in microseconds.

Parameters:

  • before (Time)

    time.

  • after (Time)

    time.

Returns:

  • (Float)

    Time difference of before and after.



191
192
193
# File 'lib/benchmark/ips/job.rb', line 191

def time_us before, after
  (after.to_f - before.to_f) * MICROSECONDS_PER_SECOND
end