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
 | 
			
		||||
 | 
			
		||||
class TestJITDebug < TestJIT
 | 
			
		||||
  @@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker?
 | 
			
		||||
 | 
			
		||||
  def setup
 | 
			
		||||
    super
 | 
			
		||||
    # let `#eval_with_jit` use --jit-debug
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -198,6 +198,9 @@ if $0 == __FILE__
 | 
			
		|||
        def on_parallel_worker?
 | 
			
		||||
          true
 | 
			
		||||
        end
 | 
			
		||||
        def self.on_parallel_worker?
 | 
			
		||||
          true
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue