module Benchmark::Perf::Execution
Measure length of time the work could take on average
@api public
Public Class Methods
Check if expected value is greater than minimum
@param [Numeric] expected @param [Numeric] min
@raise [ArgumentError]
@api private
# File lib/benchmark/perf/execution.rb, line 121 def check_greater(expected, min) unless expected > min raise ArgumentError, "Repeat value: #{expected} needs to be greater than #{min}" end end
Perform work x times
@param [Integer] repeat
how many times to repeat the code measuremenets
@example
ExecutionTime.run(repeat: 10) { ... }
@return [Array[Float, Float]]
average and standard deviation
@api public
# File lib/benchmark/perf/execution.rb, line 93 def run(repeat: 1, io: nil, warmup: 1, subprocess: true, &work) check_greater(repeat, 0) result = CPUResult.new run_warmup(warmup: warmup, io: io, subprocess: subprocess, &work) repeat.times do GC.start result << run_in_subprocess(io: io, subprocess: subprocess) do Clock.measure(&work) end end io.puts if io result end
Isolate run in subprocess
@example
iteration.run_in_subproces { ... }
@return [Float]
the elapsed time of the measurement
@api private
# File lib/benchmark/perf/execution.rb, line 29 def run_in_subprocess(subprocess: true, io: nil) return yield unless subprocess && Process.respond_to?(:fork) return yield unless run_in_subprocess? reader, writer = IO.pipe reader.binmode writer.binmode pid = Process.fork do GC.start GC.disable if ENV['BENCH_DISABLE_GC'] begin reader.close time = yield io.print "%9.6f" % data if io Marshal.dump(time, writer) rescue => error Marshal.dump(error, writer) ensure GC.enable if ENV['BENCH_DISABLE_GC'] writer.close exit # allow finalizers to run end end writer.close unless writer.closed? Process.waitpid(pid) data = Marshal.load(reader) reader.close raise data if data.is_a?(Exception) data end
Check if measurements need to run in subprocess
@api private
# File lib/benchmark/perf/execution.rb, line 15 def run_in_subprocess? ENV["RUN_IN_SUBPROCESS"] != 'false' && Process.respond_to?(:fork) end
Run warmup measurement
@param [Numeric] warmup
the warmup time
@api private
# File lib/benchmark/perf/execution.rb, line 70 def run_warmup(warmup: 1, io: nil, subprocess: true, &work) GC.start warmup.times do run_in_subprocess(io: io, subprocess: subprocess) do Clock.measure(&work) end end end
Private Instance Methods
Check if expected value is greater than minimum
@param [Numeric] expected @param [Numeric] min
@raise [ArgumentError]
@api private
# File lib/benchmark/perf/execution.rb, line 121 def check_greater(expected, min) unless expected > min raise ArgumentError, "Repeat value: #{expected} needs to be greater than #{min}" end end
Perform work x times
@param [Integer] repeat
how many times to repeat the code measuremenets
@example
ExecutionTime.run(repeat: 10) { ... }
@return [Array[Float, Float]]
average and standard deviation
@api public
# File lib/benchmark/perf/execution.rb, line 93 def run(repeat: 1, io: nil, warmup: 1, subprocess: true, &work) check_greater(repeat, 0) result = CPUResult.new run_warmup(warmup: warmup, io: io, subprocess: subprocess, &work) repeat.times do GC.start result << run_in_subprocess(io: io, subprocess: subprocess) do Clock.measure(&work) end end io.puts if io result end
Isolate run in subprocess
@example
iteration.run_in_subproces { ... }
@return [Float]
the elapsed time of the measurement
@api private
# File lib/benchmark/perf/execution.rb, line 29 def run_in_subprocess(subprocess: true, io: nil) return yield unless subprocess && Process.respond_to?(:fork) return yield unless run_in_subprocess? reader, writer = IO.pipe reader.binmode writer.binmode pid = Process.fork do GC.start GC.disable if ENV['BENCH_DISABLE_GC'] begin reader.close time = yield io.print "%9.6f" % data if io Marshal.dump(time, writer) rescue => error Marshal.dump(error, writer) ensure GC.enable if ENV['BENCH_DISABLE_GC'] writer.close exit # allow finalizers to run end end writer.close unless writer.closed? Process.waitpid(pid) data = Marshal.load(reader) reader.close raise data if data.is_a?(Exception) data end
Check if measurements need to run in subprocess
@api private
# File lib/benchmark/perf/execution.rb, line 15 def run_in_subprocess? ENV["RUN_IN_SUBPROCESS"] != 'false' && Process.respond_to?(:fork) end
Run warmup measurement
@param [Numeric] warmup
the warmup time
@api private
# File lib/benchmark/perf/execution.rb, line 70 def run_warmup(warmup: 1, io: nil, subprocess: true, &work) GC.start warmup.times do run_in_subprocess(io: io, subprocess: subprocess) do Clock.measure(&work) end end end