1
0
Fork 0
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:
Koichi Sasada 2020-12-01 01:27:04 +09:00
parent e25165b3fc
commit e79f1941b2
Notes: git 2020-12-01 09:39:33 +09:00
4 changed files with 42 additions and 1 deletions

View file

@ -7,6 +7,8 @@ return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp
return if /mswin/ =~ RUBY_PLATFORM
class TestJITDebug < TestJIT
@@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker?
def setup
super
# let `#eval_with_jit` use --jit-debug

View file

@ -1405,6 +1405,7 @@ module MiniTest
def self.test_suites # :nodoc:
suites = @@test_suites.keys
case self.test_order
when :random
# shuffle test suites based on CRC32 of their names

View file

@ -203,6 +203,10 @@ module Test
opts.on '--ruby VAL', "Path to ruby which is used at -j option" do |a|
options[:ruby] = a.split(/ /).reject(&:empty?)
end
opts.on '--timetable-data=FILE', "Path to timetable data" do |a|
options[:timetable_data] = a
end
end
class Worker
@ -216,8 +220,12 @@ module Test
end
attr_reader :quit_called
attr_accessor :start_time
@@worker_number = 0
def initialize(io, pid, status)
@num = (@@worker_number += 1)
@io = io
@pid = pid
@status = status
@ -228,6 +236,10 @@ module Test
@quit_called = false
end
def name
"Worker #{@num}"
end
def puts(*args)
@io.puts(*args)
end
@ -240,6 +252,7 @@ module Test
@loadpath = $:.dup
puts "run #{task} #{type}"
@status = :prepare
@start_time = Time.now
rescue Errno::EPIPE
died
rescue IOError
@ -405,6 +418,7 @@ module Test
worker = @workers_hash[io]
cmd = worker.read
cmd.sub!(/\A\.+/, '') if cmd # read may return nil
case cmd
when ''
# just only dots, ignore
@ -437,10 +451,19 @@ module Test
rep << {file: worker.real_file, report: r[2], result: r[3], testcase: r[5]}
$:.push(*r[4]).uniq!
jobs_status(worker) if @options[:job_status] == :replace
return true
when /^record (.+?)$/
begin
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
print "unknown record: #{e.message} #{$1.unpack("m")[0].dump}"
return true
@ -467,6 +490,8 @@ module Test
end
def _run_parallel suites, type, result
@records = {}
if @options[:parallel] < 1
warn "Error: parameter of -j option should be greater than 0."
return
@ -480,7 +505,9 @@ module Test
when :random
@tasks.shuffle!
else
# sorted
# JIT first
ts = @tasks.group_by{|e| /test_jit/ =~ e ? 0 : 1}
@tasks = ts[0] + ts[1] if ts.size == 2
end
@need_quit = false
@ -514,6 +541,14 @@ module Test
@interrupt = ex
return result
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
@ios.select!{|x| @workers_hash[x].status == :running }
while !@ios.empty? && (__io = IO.select(@ios,[],[],10))

View file

@ -198,6 +198,9 @@ if $0 == __FILE__
def on_parallel_worker?
true
end
def self.on_parallel_worker?
true
end
end
end
end