[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]