ruby-changes:63807
From: Koichi <ko1@a...>
Date: Tue, 1 Dec 2020 09:39:23 +0900 (JST)
Subject: [ruby-changes:63807] e79f1941b2 (master): tune parallel test
https://git.ruby-lang.org/ruby.git/commit/?id=e79f1941b2 From e79f1941b29738d95b42f8cb5bdb159e7138cf49 Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Tue, 1 Dec 2020 01:27:04 +0900 Subject: 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. diff --git a/test/ruby/test_jit_debug.rb b/test/ruby/test_jit_debug.rb index 179512f..50e52b4 100644 --- a/test/ruby/test_jit_debug.rb +++ b/test/ruby/test_jit_debug.rb @@ -7,6 +7,8 @@ return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit_debug.rb#L7 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 diff --git a/tool/lib/minitest/unit.rb b/tool/lib/minitest/unit.rb index c325134..f70762e 100644 --- a/tool/lib/minitest/unit.rb +++ b/tool/lib/minitest/unit.rb @@ -1405,6 +1405,7 @@ module MiniTest https://github.com/ruby/ruby/blob/trunk/tool/lib/minitest/unit.rb#L1405 def self.test_suites # :nodoc: suites = @@test_suites.keys + case self.test_order when :random # shuffle test suites based on CRC32 of their names diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb index c17f198..1ebe59b 100644 --- a/tool/lib/test/unit.rb +++ b/tool/lib/test/unit.rb @@ -203,6 +203,10 @@ module Test https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L203 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 https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L220 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 https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L236 @quit_called = false end + def name + "Worker #{@num}" + end + def puts(*args) @io.puts(*args) end @@ -240,6 +252,7 @@ module Test https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L252 @loadpath = $:.dup puts "run #{task} #{type}" @status = :prepare + @start_time = Time.now rescue Errno::EPIPE died rescue IOError @@ -405,6 +418,7 @@ module Test https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L418 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 https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L451 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 https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L490 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 https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L505 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 https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit.rb#L541 @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)) diff --git a/tool/lib/test/unit/parallel.rb b/tool/lib/test/unit/parallel.rb index afb0d01..ccaf1a9 100644 --- a/tool/lib/test/unit/parallel.rb +++ b/tool/lib/test/unit/parallel.rb @@ -198,6 +198,9 @@ if $0 == __FILE__ https://github.com/ruby/ruby/blob/trunk/tool/lib/test/unit/parallel.rb#L198 def on_parallel_worker? true end + def self.on_parallel_worker? + true + end end end end -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/