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.



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

def initialize opts={}
  @suite = opts[:suite] || nil
  @quiet = opts[:quiet] || false
  @list = []
  @compare = false
  @json_path = 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.



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

def compare
  @compare
end

#full_reportReport (readonly)

Report object containing information about the run.

Returns:

  • (Report)

    the report object.



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

def full_report
  @full_report
end

#listArray<Entry> (readonly)

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

Returns:

  • (Array<Entry>)

    list of entries



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

def list
  @list
end

#timeInteger

Calculation time setter and getter (in seconds).

Returns:

  • (Integer)


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

def time
  @time
end

#timingHash (readonly)

Storing Iterations in time period.

Returns:

  • (Hash)


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

def timing
  @timing
end

#warmupInteger

Warmup time setter and getter (in seconds).

Returns:

  • (Integer)


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

def warmup
  @warmup
end

Instance Method Details

#compare!Object

Set @compare to true.



156
157
158
# File 'lib/benchmark/ips/job.rb', line 156

def compare!
  @compare = true
end

#compare?Boolean

Return true if job needs to be compared.

Returns:

  • (Boolean)

    Need to compare?



151
152
153
# File 'lib/benchmark/ips/job.rb', line 151

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.



143
144
145
146
147
# File 'lib/benchmark/ips/job.rb', line 143

def config opts
  @warmup = opts[:warmup] if opts[:warmup]
  @time = opts[:time] if opts[:time]
  @suite = opts[:suite] if opts[:suite]
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.



332
333
334
# File 'lib/benchmark/ips/job.rb', line 332

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.



196
197
198
199
200
# File 'lib/benchmark/ips/job.rb', line 196

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

#generate_jsonObject

Generate json from @full_report.



321
322
323
# File 'lib/benchmark/ips/job.rb', line 321

def generate_json
  @full_report.generate_json @json_path
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.



178
179
180
181
182
183
184
185
186
187
188
# File 'lib/benchmark/ips/job.rb', line 178

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.



215
216
217
# File 'lib/benchmark/ips/job.rb', line 215

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

#json!(path = "data.json") ⇒ Object

Set @json_path to given path, defaults to “data.json”.



168
169
170
# File 'lib/benchmark/ips/job.rb', line 168

def json!(path="data.json")
  @json_path = path
end

#json?Boolean

Return true if job needs to generate json.

Returns:

  • (Boolean)

    Need to generate json?



163
164
165
# File 'lib/benchmark/ips/job.rb', line 163

def json?
  !!@json_path
end

#runObject

Run calculation.



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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/benchmark/ips/job.rb', line 258

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.



316
317
318
# File 'lib/benchmark/ips/job.rb', line 316

def run_comparison
  @full_report.run_comparison
end

#run_warmupObject

Run warmup.



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/benchmark/ips/job.rb', line 220

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

    unless @quiet
      $stdout.print 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.



206
207
208
# File 'lib/benchmark/ips/job.rb', line 206

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