mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
tune parallel test
This patch contains the fowllowing hacks: (1) Add "--timetable-data=FILE" option for test-all This option enables to dump timeline event contains worker, suite, and start/end time. (2) remove TestJIT in test_jit_debug.rb on parallel test. it is duplicated test. (3) move test_jit.rb and test_jit_debug.rb at first because these two tests are bottleneck of parallel tests. On my environment, `make test-all TESTS=-j12` reduced the total time 190 seconds -> 140 seconds.
This commit is contained in:
parent
e25165b3fc
commit
e79f1941b2
Notes:
git
2020-12-01 09:39:33 +09:00
4 changed files with 42 additions and 1 deletions
|
@ -7,6 +7,8 @@ return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp
|
||||||
return if /mswin/ =~ RUBY_PLATFORM
|
return if /mswin/ =~ RUBY_PLATFORM
|
||||||
|
|
||||||
class TestJITDebug < TestJIT
|
class TestJITDebug < TestJIT
|
||||||
|
@@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker?
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
super
|
super
|
||||||
# let `#eval_with_jit` use --jit-debug
|
# let `#eval_with_jit` use --jit-debug
|
||||||
|
|
|
@ -1405,6 +1405,7 @@ module MiniTest
|
||||||
|
|
||||||
def self.test_suites # :nodoc:
|
def self.test_suites # :nodoc:
|
||||||
suites = @@test_suites.keys
|
suites = @@test_suites.keys
|
||||||
|
|
||||||
case self.test_order
|
case self.test_order
|
||||||
when :random
|
when :random
|
||||||
# shuffle test suites based on CRC32 of their names
|
# shuffle test suites based on CRC32 of their names
|
||||||
|
|
|
@ -203,6 +203,10 @@ module Test
|
||||||
opts.on '--ruby VAL', "Path to ruby which is used at -j option" do |a|
|
opts.on '--ruby VAL', "Path to ruby which is used at -j option" do |a|
|
||||||
options[:ruby] = a.split(/ /).reject(&:empty?)
|
options[:ruby] = a.split(/ /).reject(&:empty?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
opts.on '--timetable-data=FILE', "Path to timetable data" do |a|
|
||||||
|
options[:timetable_data] = a
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Worker
|
class Worker
|
||||||
|
@ -216,8 +220,12 @@ module Test
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :quit_called
|
attr_reader :quit_called
|
||||||
|
attr_accessor :start_time
|
||||||
|
|
||||||
|
@@worker_number = 0
|
||||||
|
|
||||||
def initialize(io, pid, status)
|
def initialize(io, pid, status)
|
||||||
|
@num = (@@worker_number += 1)
|
||||||
@io = io
|
@io = io
|
||||||
@pid = pid
|
@pid = pid
|
||||||
@status = status
|
@status = status
|
||||||
|
@ -228,6 +236,10 @@ module Test
|
||||||
@quit_called = false
|
@quit_called = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
"Worker #{@num}"
|
||||||
|
end
|
||||||
|
|
||||||
def puts(*args)
|
def puts(*args)
|
||||||
@io.puts(*args)
|
@io.puts(*args)
|
||||||
end
|
end
|
||||||
|
@ -240,6 +252,7 @@ module Test
|
||||||
@loadpath = $:.dup
|
@loadpath = $:.dup
|
||||||
puts "run #{task} #{type}"
|
puts "run #{task} #{type}"
|
||||||
@status = :prepare
|
@status = :prepare
|
||||||
|
@start_time = Time.now
|
||||||
rescue Errno::EPIPE
|
rescue Errno::EPIPE
|
||||||
died
|
died
|
||||||
rescue IOError
|
rescue IOError
|
||||||
|
@ -405,6 +418,7 @@ module Test
|
||||||
worker = @workers_hash[io]
|
worker = @workers_hash[io]
|
||||||
cmd = worker.read
|
cmd = worker.read
|
||||||
cmd.sub!(/\A\.+/, '') if cmd # read may return nil
|
cmd.sub!(/\A\.+/, '') if cmd # read may return nil
|
||||||
|
|
||||||
case cmd
|
case cmd
|
||||||
when ''
|
when ''
|
||||||
# just only dots, ignore
|
# just only dots, ignore
|
||||||
|
@ -437,10 +451,19 @@ module Test
|
||||||
rep << {file: worker.real_file, report: r[2], result: r[3], testcase: r[5]}
|
rep << {file: worker.real_file, report: r[2], result: r[3], testcase: r[5]}
|
||||||
$:.push(*r[4]).uniq!
|
$:.push(*r[4]).uniq!
|
||||||
jobs_status(worker) if @options[:job_status] == :replace
|
jobs_status(worker) if @options[:job_status] == :replace
|
||||||
|
|
||||||
return true
|
return true
|
||||||
when /^record (.+?)$/
|
when /^record (.+?)$/
|
||||||
begin
|
begin
|
||||||
r = Marshal.load($1.unpack("m")[0])
|
r = Marshal.load($1.unpack("m")[0])
|
||||||
|
|
||||||
|
suite = r.first
|
||||||
|
key = [worker.name, suite]
|
||||||
|
if @records[key]
|
||||||
|
@records[key][1] = worker.start_time = Time.now
|
||||||
|
else
|
||||||
|
@records[key] = [worker.start_time, Time.now]
|
||||||
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
print "unknown record: #{e.message} #{$1.unpack("m")[0].dump}"
|
print "unknown record: #{e.message} #{$1.unpack("m")[0].dump}"
|
||||||
return true
|
return true
|
||||||
|
@ -467,6 +490,8 @@ module Test
|
||||||
end
|
end
|
||||||
|
|
||||||
def _run_parallel suites, type, result
|
def _run_parallel suites, type, result
|
||||||
|
@records = {}
|
||||||
|
|
||||||
if @options[:parallel] < 1
|
if @options[:parallel] < 1
|
||||||
warn "Error: parameter of -j option should be greater than 0."
|
warn "Error: parameter of -j option should be greater than 0."
|
||||||
return
|
return
|
||||||
|
@ -480,7 +505,9 @@ module Test
|
||||||
when :random
|
when :random
|
||||||
@tasks.shuffle!
|
@tasks.shuffle!
|
||||||
else
|
else
|
||||||
# sorted
|
# JIT first
|
||||||
|
ts = @tasks.group_by{|e| /test_jit/ =~ e ? 0 : 1}
|
||||||
|
@tasks = ts[0] + ts[1] if ts.size == 2
|
||||||
end
|
end
|
||||||
|
|
||||||
@need_quit = false
|
@need_quit = false
|
||||||
|
@ -514,6 +541,14 @@ module Test
|
||||||
@interrupt = ex
|
@interrupt = ex
|
||||||
return result
|
return result
|
||||||
ensure
|
ensure
|
||||||
|
if file = @options[:timetable_data]
|
||||||
|
open(file, 'w'){|f|
|
||||||
|
@records.each{|(worker, suite), (st, ed)|
|
||||||
|
f.puts '[' + [worker.dump, suite.dump, st.to_f * 1_000, ed.to_f * 1_000].join(", ") + '],'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
if @interrupt
|
if @interrupt
|
||||||
@ios.select!{|x| @workers_hash[x].status == :running }
|
@ios.select!{|x| @workers_hash[x].status == :running }
|
||||||
while !@ios.empty? && (__io = IO.select(@ios,[],[],10))
|
while !@ios.empty? && (__io = IO.select(@ios,[],[],10))
|
||||||
|
|
|
@ -198,6 +198,9 @@ if $0 == __FILE__
|
||||||
def on_parallel_worker?
|
def on_parallel_worker?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
def self.on_parallel_worker?
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue