Skip to content

Commit 6afd8ff

Browse files
committed
Move default executable selection into ArgumentParser
1 parent 0008f90 commit 6afd8ff

File tree

3 files changed

+132
-32
lines changed

3 files changed

+132
-32
lines changed

lib/argument_parser.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require 'optparse'
22
require 'shellwords'
3+
require 'rbconfig'
34

45
class ArgumentParser
56
Args = Struct.new(
@@ -19,8 +20,12 @@ class ArgumentParser
1920
keyword_init: true
2021
)
2122

22-
def self.parse(argv = ARGV)
23-
new.parse(argv)
23+
def self.parse(argv = ARGV, ruby_executable: RbConfig.ruby)
24+
new(ruby_executable: ruby_executable).parse(argv)
25+
end
26+
27+
def initialize(ruby_executable: RbConfig.ruby)
28+
@ruby_executable = ruby_executable
2429
end
2530

2631
def parse(argv)
@@ -140,11 +145,26 @@ def parse(argv)
140145
args.name_filters += argv
141146
end
142147

148+
# If -e is not specified, benchmark the current Ruby. Compare it with YJIT if available.
149+
if args.executables.empty?
150+
if have_yjit?(@ruby_executable) && !args.skip_yjit
151+
args.executables["interp"] = [@ruby_executable]
152+
args.executables["yjit"] = [@ruby_executable, "--yjit", *args.yjit_opts.shellsplit]
153+
else
154+
args.executables["ruby"] = [@ruby_executable]
155+
end
156+
end
157+
143158
args
144159
end
145160

146161
private
147162

163+
def have_yjit?(ruby)
164+
ruby_version = `#{ruby} -v --yjit 2> #{File::NULL}`.strip
165+
ruby_version.downcase.include?("yjit")
166+
end
167+
148168
def default_args
149169
Args.new(
150170
executables: {},

run_benchmarks.rb

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,6 @@
1515
require_relative 'lib/benchmark_filter'
1616
require_relative 'lib/argument_parser'
1717

18-
def have_yjit?(ruby)
19-
ruby_version = `#{ruby} -v --yjit 2> #{File::NULL}`.strip
20-
ruby_version.downcase.include?("yjit")
21-
end
22-
2318
def mean(values)
2419
Stats.new(values).mean
2520
end
@@ -159,16 +154,6 @@ def run_benchmarks(ruby:, ruby_description:, categories:, name_filters:, out_pat
159154

160155
args = ArgumentParser.parse(ARGV)
161156

162-
# If -e is not specified, benchmark the current Ruby. Compare it with YJIT if available.
163-
if args.executables.empty?
164-
if have_yjit?(RbConfig.ruby) && !args.skip_yjit
165-
args.executables["interp"] = [RbConfig.ruby]
166-
args.executables["yjit"] = [RbConfig.ruby, "--yjit", *args.yjit_opts.shellsplit]
167-
else
168-
args.executables["ruby"] = [RbConfig.ruby]
169-
end
170-
end
171-
172157
CPUConfig.configure_for_benchmarking(turbo: args.turbo)
173158

174159
# Create the output directory

test/argument_parser_test.rb

Lines changed: 110 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,26 @@ def setup_mock_ruby(path)
3434

3535
describe '#parse' do
3636
it 'returns default values when no arguments provided' do
37-
parser = ArgumentParser.new
38-
args = parser.parse([])
39-
40-
assert_equal({}, args.executables)
41-
assert_equal File.expand_path("./data"), args.out_path
42-
assert_nil args.out_override
43-
assert_equal "harness", args.harness
44-
assert_equal "", args.yjit_opts
45-
assert_equal [], args.categories
46-
assert_equal [], args.name_filters
47-
assert_equal false, args.rss
48-
assert_equal false, args.graph
49-
assert_equal false, args.no_pinning
50-
assert_equal false, args.turbo
51-
assert_equal false, args.skip_yjit
37+
mock_ruby = '/usr/bin/ruby'
38+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
39+
40+
# Stub to return false so we get a single 'ruby' executable
41+
parser.stub :have_yjit?, false do
42+
args = parser.parse([])
43+
44+
assert_equal({ 'ruby' => [mock_ruby] }, args.executables)
45+
assert_equal File.expand_path("./data"), args.out_path
46+
assert_nil args.out_override
47+
assert_equal "harness", args.harness
48+
assert_equal "", args.yjit_opts
49+
assert_equal [], args.categories
50+
assert_equal [], args.name_filters
51+
assert_equal false, args.rss
52+
assert_equal false, args.graph
53+
assert_equal false, args.no_pinning
54+
assert_equal false, args.turbo
55+
assert_equal false, args.skip_yjit
56+
end
5257
end
5358

5459
describe '-e option' do
@@ -502,5 +507,95 @@ def setup_mock_ruby(path)
502507
assert_equal true, args.rss
503508
end
504509
end
510+
511+
describe 'default executables' do
512+
it 'sets ruby executable when no -e option and no YJIT' do
513+
mock_ruby = '/usr/bin/ruby'
514+
515+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
516+
517+
parser.stub :have_yjit?, false do
518+
args = parser.parse([])
519+
520+
assert_equal 1, args.executables.size
521+
assert_equal [mock_ruby], args.executables['ruby']
522+
end
523+
end
524+
525+
it 'sets interp and yjit executables when no -e option and YJIT available' do
526+
mock_ruby = '/usr/bin/ruby'
527+
528+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
529+
530+
parser.stub :have_yjit?, true do
531+
args = parser.parse([])
532+
533+
assert_equal 2, args.executables.size
534+
assert_equal [mock_ruby], args.executables['interp']
535+
assert_equal [mock_ruby, '--yjit'], args.executables['yjit']
536+
end
537+
end
538+
539+
it 'includes yjit_opts in default yjit executable' do
540+
mock_ruby = '/usr/bin/ruby'
541+
542+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
543+
544+
parser.stub :have_yjit?, true do
545+
args = parser.parse(['--yjit_opts=--yjit-call-threshold=10'])
546+
547+
assert_equal 2, args.executables.size
548+
assert_equal [mock_ruby], args.executables['interp']
549+
assert_equal [mock_ruby, '--yjit', '--yjit-call-threshold=10'], args.executables['yjit']
550+
end
551+
end
552+
553+
it 'respects --skip-yjit flag when YJIT is available' do
554+
mock_ruby = '/usr/bin/ruby'
555+
556+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
557+
558+
parser.stub :have_yjit?, true do
559+
args = parser.parse(['--skip-yjit'])
560+
561+
assert_equal 1, args.executables.size
562+
assert_equal [mock_ruby], args.executables['ruby']
563+
end
564+
end
565+
566+
it 'does not set default executables when -e option is provided' do
567+
mock_ruby = '/usr/bin/ruby'
568+
569+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
570+
571+
parser.stub :have_yjit?, true do
572+
args = parser.parse(['-e', 'custom::custom-ruby'])
573+
574+
assert_equal 1, args.executables.size
575+
assert_equal ['custom-ruby'], args.executables['custom']
576+
end
577+
end
578+
579+
it 'does not set default executables when --chruby option is provided' do
580+
Dir.mktmpdir do |tmpdir|
581+
@temp_home = tmpdir
582+
rubies_dir = File.join(tmpdir, '.rubies')
583+
ruby_path = File.join(rubies_dir, '3.2.0/bin/ruby')
584+
setup_mock_ruby(ruby_path)
585+
586+
ENV['HOME'] = tmpdir
587+
mock_ruby = '/usr/bin/ruby'
588+
589+
parser = ArgumentParser.new(ruby_executable: mock_ruby)
590+
591+
parser.stub :have_yjit?, true do
592+
args = parser.parse(['--chruby=test::3.2.0'])
593+
594+
assert_equal 1, args.executables.size
595+
assert_equal ruby_path, args.executables['test'].first
596+
end
597+
end
598+
end
599+
end
505600
end
506601
end

0 commit comments

Comments
 (0)