Skip to content

Commit 59333fb

Browse files
authored
Merge pull request #450 from ruby/rmf-performance
Build BenchmarkSuite only once per CLI run
2 parents edde959 + 71cdca0 commit 59333fb

File tree

3 files changed

+48
-92
lines changed

3 files changed

+48
-92
lines changed

lib/benchmark_runner/cli.rb

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,27 @@ def run
2828

2929
ruby_descriptions = {}
3030

31+
suite = BenchmarkSuite.new(
32+
categories: args.categories,
33+
name_filters: args.name_filters,
34+
excludes: args.excludes,
35+
out_path: args.out_path,
36+
harness: args.harness,
37+
pre_init: args.with_pre_init,
38+
no_pinning: args.no_pinning
39+
)
40+
3141
# Benchmark with and without YJIT
3242
bench_start_time = Time.now.to_f
3343
bench_data = {}
3444
bench_failures = {}
3545
args.executables.each do |name, executable|
3646
ruby_descriptions[name] = `#{executable.shelljoin} -v`.chomp
3747

38-
suite = BenchmarkSuite.new(
48+
bench_data[name], failures = suite.run(
3949
ruby: executable,
40-
ruby_description: ruby_descriptions[name],
41-
categories: args.categories,
42-
name_filters: args.name_filters,
43-
excludes: args.excludes,
44-
out_path: args.out_path,
45-
harness: args.harness,
46-
pre_init: args.with_pre_init,
47-
no_pinning: args.no_pinning
50+
ruby_description: ruby_descriptions[name]
4851
)
49-
bench_data[name], failures = suite.run
5052
# Make it easier to query later.
5153
bench_failures[name] = failures unless failures.empty?
5254
end

lib/benchmark_suite.rb

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ class BenchmarkSuite
1919
RACTOR_CATEGORY = ["ractor"].freeze
2020
RACTOR_HARNESS = "harness-ractor"
2121

22-
attr_reader :ruby, :ruby_description, :categories, :name_filters, :excludes, :out_path, :harness, :pre_init, :no_pinning, :bench_dir, :ractor_bench_dir
22+
attr_reader :categories, :name_filters, :excludes, :out_path, :harness, :pre_init, :no_pinning, :bench_dir, :ractor_bench_dir
2323

24-
def initialize(ruby:, ruby_description:, categories:, name_filters:, excludes: [], out_path:, harness:, pre_init: nil, no_pinning: false)
25-
@ruby = ruby
26-
@ruby_description = ruby_description
24+
def initialize(categories:, name_filters:, excludes: [], out_path:, harness:, pre_init: nil, no_pinning: false)
2725
@categories = categories
2826
@name_filters = name_filters
2927
@excludes = excludes
@@ -38,17 +36,19 @@ def initialize(ruby:, ruby_description:, categories:, name_filters:, excludes: [
3836

3937
# Run all the benchmarks and record execution times
4038
# Returns [bench_data, bench_failures]
41-
def run
39+
def run(ruby:, ruby_description:)
4240
bench_data = {}
4341
bench_failures = {}
4442

4543
benchmark_entries = discover_benchmarks
44+
cmd_prefix = base_cmd(ruby_description)
45+
env = benchmark_env(ruby)
4646

4747
benchmark_entries.each_with_index do |entry, idx|
4848
puts("Running benchmark \"#{entry.name}\" (#{idx+1}/#{benchmark_entries.length})")
4949

5050
result_json_path = File.join(out_path, "temp#{Process.pid}.json")
51-
result = run_single_benchmark(entry.script_path, result_json_path)
51+
result = run_single_benchmark(entry.script_path, result_json_path, ruby, cmd_prefix, env)
5252

5353
if result[:success]
5454
bench_data[entry.name] = process_benchmark_result(result_json_path, result[:command])
@@ -142,47 +142,45 @@ def filter_entries(entries, categories:, name_filters:, excludes:, directory_map
142142
entries.select { |entry| filter.match?(entry.name) }
143143
end
144144

145-
def run_single_benchmark(script_path, result_json_path)
145+
def run_single_benchmark(script_path, result_json_path, ruby, cmd_prefix, env)
146146
# Fix for jruby/jruby#7394 in JRuby 9.4.2.0
147147
script_path = File.expand_path(script_path)
148148

149149
# Set up the environment for the benchmarking command
150150
ENV["RESULT_JSON_PATH"] = result_json_path
151151

152152
# Set up the benchmarking command
153-
cmd = base_cmd + [
153+
cmd = cmd_prefix + [
154154
*ruby,
155155
"-I", harness,
156156
*pre_init,
157157
script_path,
158158
].compact
159159

160160
# Do the benchmarking
161-
result = BenchmarkRunner.check_call(cmd.shelljoin, env: benchmark_env, raise_error: false)
161+
result = BenchmarkRunner.check_call(cmd.shelljoin, env: env, raise_error: false)
162162
result[:command] = cmd.shelljoin
163163
result
164164
end
165165

166-
def benchmark_env
167-
@benchmark_env ||= begin
168-
# When the Ruby running this script is not the first Ruby in PATH, shell commands
169-
# like `bundle install` in a child process will not use the Ruby being benchmarked.
170-
# It overrides PATH to guarantee the commands of the benchmarked Ruby will be used.
171-
env = {}
172-
ruby_path = `#{ruby.shelljoin} -e 'print RbConfig.ruby' 2> #{File::NULL}`
166+
def benchmark_env(ruby)
167+
# When the Ruby running this script is not the first Ruby in PATH, shell commands
168+
# like `bundle install` in a child process will not use the Ruby being benchmarked.
169+
# It overrides PATH to guarantee the commands of the benchmarked Ruby will be used.
170+
env = {}
171+
ruby_path = `#{ruby.shelljoin} -e 'print RbConfig.ruby' 2> #{File::NULL}`
173172

174-
if ruby_path != RbConfig.ruby
175-
env["PATH"] = "#{File.dirname(ruby_path)}:#{ENV["PATH"]}"
173+
if ruby_path != RbConfig.ruby
174+
env["PATH"] = "#{File.dirname(ruby_path)}:#{ENV["PATH"]}"
176175

177-
# chruby sets GEM_HOME and GEM_PATH in your shell. We have to unset it in the child
178-
# process to avoid installing gems to the version that is running run_benchmarks.rb.
179-
["GEM_HOME", "GEM_PATH"].each do |var|
180-
env[var] = nil if ENV.key?(var)
181-
end
176+
# chruby sets GEM_HOME and GEM_PATH in your shell. We have to unset it in the child
177+
# process to avoid installing gems to the version that is running run_benchmarks.rb.
178+
["GEM_HOME", "GEM_PATH"].each do |var|
179+
env[var] = nil if ENV.key?(var)
182180
end
183-
184-
env
185181
end
182+
183+
env
186184
end
187185

188186
def benchmarks_metadata
@@ -199,8 +197,8 @@ def linux?
199197
end
200198

201199
# Set up the base command with CPU pinning if needed
202-
def base_cmd
203-
@base_cmd ||= if linux?
200+
def base_cmd(ruby_description)
201+
if linux?
204202
cmd = setarch_prefix
205203

206204
# Pin the process to one given core to improve caching and reduce variance on CRuby

0 commit comments

Comments
 (0)