mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add a benchmark-driver runner for Ractor (#4172)
* Add a benchmark-driver runner for Ractor * Process.clock_gettime(Process:CLOCK_MONOTONIC) could be slow in Ruby 3.0 Ractor * Fetching Time could also be slow * Fix a comment * Assert overriding a private method
This commit is contained in:
parent
9e66c511ff
commit
27382eb9fc
Notes:
git
2021-02-11 14:24:47 +09:00
Merged-By: k0kubun <takashikkbn@gmail.com>
4 changed files with 132 additions and 1 deletions
119
benchmark/lib/benchmark_driver/runner/ractor.rb
Normal file
119
benchmark/lib/benchmark_driver/runner/ractor.rb
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
require 'erb'
|
||||||
|
|
||||||
|
# A runner to measure performance *inside* Ractor
|
||||||
|
class BenchmarkDriver::Runner::Ractor < BenchmarkDriver::Runner::Ips
|
||||||
|
# JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job"
|
||||||
|
Job = Class.new(BenchmarkDriver::DefaultJob) do
|
||||||
|
attr_accessor :ractor
|
||||||
|
end
|
||||||
|
|
||||||
|
# Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
|
||||||
|
JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]).extend(Module.new{
|
||||||
|
def parse(ractor: 1, **kwargs)
|
||||||
|
super(**kwargs).each do |job|
|
||||||
|
job.ractor = ractor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
unless private_instance_methods.include?(:run_benchmark)
|
||||||
|
raise "#run_benchmark is no longer defined in BenchmarkDriver::Runner::Ips"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [BenchmarkDriver::Runner::Ips::Job] job - loop_count is not nil
|
||||||
|
# @param [BenchmarkDriver::Context] context
|
||||||
|
# @return [BenchmarkDriver::Metrics]
|
||||||
|
def run_benchmark(job, context:)
|
||||||
|
benchmark = BenchmarkScript.new(
|
||||||
|
preludes: [context.prelude, job.prelude],
|
||||||
|
script: job.script,
|
||||||
|
teardown: job.teardown,
|
||||||
|
loop_count: job.loop_count,
|
||||||
|
)
|
||||||
|
|
||||||
|
results = job.ractor.times.map do
|
||||||
|
Tempfile.open('benchmark_driver_result')
|
||||||
|
end
|
||||||
|
duration = with_script(benchmark.render(results: results.map(&:path))) do |path|
|
||||||
|
success = execute(*context.executable.command, path, exception: false)
|
||||||
|
if success && ((value = results.map { |f| Float(f.read) }.max) > 0)
|
||||||
|
value
|
||||||
|
else
|
||||||
|
BenchmarkDriver::Result::ERROR
|
||||||
|
end
|
||||||
|
end
|
||||||
|
results.each(&:close)
|
||||||
|
|
||||||
|
value_duration(
|
||||||
|
loop_count: job.loop_count,
|
||||||
|
duration: duration,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [String] prelude
|
||||||
|
# @param [String] script
|
||||||
|
# @param [String] teardown
|
||||||
|
# @param [Integer] loop_count
|
||||||
|
BenchmarkScript = ::BenchmarkDriver::Struct.new(:preludes, :script, :teardown, :loop_count) do
|
||||||
|
# @param [String] result - A file to write result
|
||||||
|
def render(results:)
|
||||||
|
prelude = preludes.reject(&:nil?).reject(&:empty?).join("\n")
|
||||||
|
ERB.new(<<-RUBY).result_with_hash(results: results)
|
||||||
|
Warning[:experimental] = false
|
||||||
|
# shareable-constant-value: experimental_everything
|
||||||
|
#{prelude}
|
||||||
|
|
||||||
|
if #{loop_count} == 1
|
||||||
|
__bmdv_empty_before = 0
|
||||||
|
__bmdv_empty_after = 0
|
||||||
|
else
|
||||||
|
__bmdv_empty_before = Time.new
|
||||||
|
#{while_loop('', loop_count, id: 0)}
|
||||||
|
__bmdv_empty_after = Time.new
|
||||||
|
end
|
||||||
|
|
||||||
|
ractors = []
|
||||||
|
<% results.each do |result| %>
|
||||||
|
ractors << Ractor.new(__bmdv_empty_after - __bmdv_empty_before) { |loop_time|
|
||||||
|
__bmdv_time = Time
|
||||||
|
__bmdv_script_before = __bmdv_time.new
|
||||||
|
#{while_loop(script, loop_count, id: 1)}
|
||||||
|
__bmdv_script_after = __bmdv_time.new
|
||||||
|
|
||||||
|
File.write(
|
||||||
|
<%= result.dump %>,
|
||||||
|
((__bmdv_script_after - __bmdv_script_before) - loop_time).inspect,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<% end %>
|
||||||
|
ractors.each(&:take)
|
||||||
|
|
||||||
|
#{teardown}
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# id is to prevent:
|
||||||
|
# can not isolate a Proc because it accesses outer variables (__bmdv_i)
|
||||||
|
def while_loop(content, times, id:)
|
||||||
|
if !times.is_a?(Integer) || times <= 0
|
||||||
|
raise ArgumentError.new("Unexpected times: #{times.inspect}")
|
||||||
|
elsif times == 1
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: execute in batch
|
||||||
|
<<-RUBY
|
||||||
|
__bmdv_i#{id} = 0
|
||||||
|
while __bmdv_i#{id} < #{times}
|
||||||
|
#{content}
|
||||||
|
__bmdv_i#{id} += 1
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
private_constant :BenchmarkScript
|
||||||
|
end
|
4
benchmark/ractor_const.yml
Normal file
4
benchmark/ractor_const.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
type: lib/benchmark_driver/runner/ractor
|
||||||
|
benchmark:
|
||||||
|
ractor_const: Object
|
||||||
|
ractor: 1
|
8
benchmark/ractor_float_to_s.yml
Normal file
8
benchmark/ractor_float_to_s.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
type: lib/benchmark_driver/runner/ractor
|
||||||
|
prelude: |
|
||||||
|
FLOATS = [*0.0.step(1.0, 0.001)]
|
||||||
|
benchmark:
|
||||||
|
ractor_float_to_s: |
|
||||||
|
FLOATS.each {|f| f.to_s}
|
||||||
|
loop_count: 100
|
||||||
|
ractor: 2
|
|
@ -48,7 +48,7 @@ GEM_PATH =
|
||||||
GEM_VENDOR =
|
GEM_VENDOR =
|
||||||
|
|
||||||
BENCHMARK_DRIVER_GIT_URL = https://github.com/benchmark-driver/benchmark-driver
|
BENCHMARK_DRIVER_GIT_URL = https://github.com/benchmark-driver/benchmark-driver
|
||||||
BENCHMARK_DRIVER_GIT_REF = v0.15.15
|
BENCHMARK_DRIVER_GIT_REF = v0.15.17
|
||||||
SIMPLECOV_GIT_URL = https://github.com/colszowka/simplecov.git
|
SIMPLECOV_GIT_URL = https://github.com/colszowka/simplecov.git
|
||||||
SIMPLECOV_GIT_REF = v0.17.0
|
SIMPLECOV_GIT_REF = v0.17.0
|
||||||
SIMPLECOV_HTML_GIT_URL = https://github.com/colszowka/simplecov-html.git
|
SIMPLECOV_HTML_GIT_URL = https://github.com/colszowka/simplecov-html.git
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue