Title: [271179] trunk/Tools
Revision
271179
Author
[email protected]
Date
2021-01-05 15:14:21 -0800 (Tue, 05 Jan 2021)

Log Message

[JSC] allow stress tests to opt out of parallel execution
https://bugs.webkit.org/show_bug.cgi?id=213373

Patch by Angelos Oikonomopoulos <[email protected]> on 2021-01-05
Reviewed by Yusuke Suzuki.

On memory-limited devices, some JSC stress tests may intermittently OOM when
they get scheduled along with another heavy JSC stress test. However, the tests
might be able to complete if run on their own.

This patch adds a serial! directive that causes a JSC stress test to only ever
be scheduled to run by itself. It's currently unused and needs to be enabled on
a test-by-test basis.

* Scripts/run-jsc-stress-tests:
* Scripts/webkitruby/jsc-stress-test-writer-default.rb:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (271178 => 271179)


--- trunk/Tools/ChangeLog	2021-01-05 23:02:40 UTC (rev 271178)
+++ trunk/Tools/ChangeLog	2021-01-05 23:14:21 UTC (rev 271179)
@@ -1,3 +1,21 @@
+2021-01-05  Angelos Oikonomopoulos  <[email protected]>
+
+        [JSC] allow stress tests to opt out of parallel execution
+        https://bugs.webkit.org/show_bug.cgi?id=213373
+
+        Reviewed by Yusuke Suzuki.
+
+        On memory-limited devices, some JSC stress tests may intermittently OOM when
+        they get scheduled along with another heavy JSC stress test. However, the tests
+        might be able to complete if run on their own.
+
+        This patch adds a serial! directive that causes a JSC stress test to only ever
+        be scheduled to run by itself. It's currently unused and needs to be enabled on
+        a test-by-test basis.
+
+        * Scripts/run-jsc-stress-tests:
+        * Scripts/webkitruby/jsc-stress-test-writer-default.rb:
+
 2021-01-05  Ryan Haddad  <[email protected]>
 
         Unreviewed, reverting r271169.

Modified: trunk/Tools/Scripts/run-jsc-stress-tests (271178 => 271179)


--- trunk/Tools/Scripts/run-jsc-stress-tests	2021-01-05 23:02:40 UTC (rev 271178)
+++ trunk/Tools/Scripts/run-jsc-stress-tests	2021-01-05 23:14:21 UTC (rev 271179)
@@ -551,6 +551,7 @@
 
 COLLECT_CONTINUOUSLY_OPTIONS = shouldCollectContinuously? ? ["--collectContinuously=true", "--useGenerationalGC=false"] : []
 
+$serialRunlist = []
 $runlist = []
 
 def frameworkFromJSCPath(jscPath)
@@ -618,6 +619,14 @@
         $benchmarkDirectory, command, "#{$collectionName}/#{$benchmark}", name, outputHandler,
         errorHandler)
     plan.additionalEnv.push(*additionalEnv)
+    if $runCommandOptions[:serial]
+        # Add this to the list of tests to be run on their own, so
+        # that we can treat them specially when scheduling, but keep
+        # it in the $runlist for code that dosn't care about
+        # scheduling.
+        $serialRunlist << plan
+    end
+
     if $numChildProcesses > 1 and $runCommandOptions[:isSlow]
         $runlist.unshift plan
     else
@@ -669,6 +678,10 @@
     $runCommandOptions[:crashOK] = true
 end
 
+def serial!
+    $runCommandOptions[:serial] = true
+end
+
 def requireOptions(*options)
     $testSpecificRequiredOptions += options
 end
@@ -2389,19 +2402,29 @@
     detectFailures
 end
 
-def prepareGnuParallelTestRunner
-    path = $runnerDir + "parallel-tests"
+def prepareGnuParallelRunnerJobs(name, runlist, exclude)
+    path = $runnerDir + name
     FileUtils.mkdir_p($runnerDir)
 
     File.open(path, "w") {
         | outp |
-        $runlist.each {
+        runlist.each {
             | plan |
+            if exclude.has_key?(plan)
+                next
+            end
             outp.puts("./test_script_#{plan.index}")
         }
     }
 end
 
+def prepareGnuParallelTestRunner
+    serialTests = {}
+    $serialRunlist.each { |p| serialTests[p] = nil }
+    prepareGnuParallelRunnerJobs("parallel-tests", $runlist, serialTests)
+    prepareGnuParallelRunnerJobs("serial-tests", $serialRunlist, {})
+end
+
 def withGnuParallelSshWrapper(&blk)
     Tempfile.open('ssh-wrapper', $runnerDir) {
         | wrapper |
@@ -2461,21 +2484,24 @@
     }
 end
 
-def runGnuParallelRunner
-    inputs = $runnerDir + "parallel-tests"
+def runGnuParallelRunner(inputs, options={})
     timeout = 300
     if ENV["JSCTEST_timeout"]
         timeout = ENV["JSCTEST_timeout"].to_f.ceil.to_i
     end
+    # We add 1 to make sure we always have waiting jobs and
+    # don't run into stalls due to ssh latency. However, we
+    # want to respect numChildProcesses, so we don't just use
+    # the -j +1 GNU parallel idiom.
+    parallelJobsOnEachHost = $numChildProcesses + 1
+    if options[:parallelJobsOnEachHost]
+      parallelJobsOnEachHost = options[:parallelJobsOnEachHost]
+    end
     withGnuParallelSshLoginFile {
         | slf |
         cmd = [
             "parallel",
-            # We add 1 to make sure we always have waiting jobs and
-            # don't run into stalls due to ssh latency. However, we
-            # want to respect numChildProcesses, so we don't just use
-            # the -j +1 GNU parallel idiom.
-            "-j", "#{$numChildProcesses + 1}",
+            "-j", "#{parallelJobsOnEachHost}",
             "--retries 5",
             "--line-buffer", # we know our output is line-oriented
             "--slf", slf,
@@ -2508,7 +2534,9 @@
     if $remoteHosts.size == 0
         raise "All remote hosts failed, giving up"
     end
-    runGnuParallelRunner
+    runGnuParallelRunner($runnerDir + "serial-tests",
+                         { :parallelJobsOnEachHost => 1})
+    runGnuParallelRunner($runnerDir + "parallel-tests")
     detectFailures
 end
 

Modified: trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-default.rb (271178 => 271179)


--- trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-default.rb	2021-01-05 23:02:40 UTC (rev 271178)
+++ trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-default.rb	2021-01-05 23:14:21 UTC (rev 271179)
@@ -305,17 +305,27 @@
     FileUtils.cp SCRIPTS_PATH + "jsc-stress-test-helpers" + "shell-runner.sh", $runnerDir + "runscript"
 end
 
+def output_target(outp, plan, prereqs)
+    index = plan.index
+    target = "test_done_#{index}"
+    outp.puts "#{target}: #{prereqs.join(" ")}"
+    outp.puts "\tsh test_script_#{index}"
+    target
+end
+
 def prepareMakeTestRunner(remoteIndex)
     # The goals of our parallel test runner are scalability and simplicity. The
     # simplicity part is particularly important. We don't want to have to have
     # a full-time contributor just philosophising about parallel testing.
     #
-    # As such, we just pass off all of the hard work to 'make'. This creates a
-    # dummy directory ("$outputDir/.runner") in which we create a dummy
-    # Makefile. The Makefile has an 'all' rule that depends on all of the tests.
-    # That is, for each test we know we will run, there is a rule in the
-    # Makefile and 'all' depends on it. Running 'make -j <whatever>' on this
-    # Makefile results in 'make' doing all of the hard work:
+    # As such, we just pass off all of the hard work to 'make'. This
+    # creates a dummy directory ("$outputDir/.runner") in which we
+    # create a dummy Makefile. The Makefile has a 'parallel' rule that
+    # depends all tests, other than the ones marked 'serial'. The
+    # serial tests are arranged in a chain; the last target in the
+    # serial chain depends on 'parallel' and 'all' depends on the head
+    # of the chain. Running 'make -j <whatever>' on this Makefile
+    # results in 'make' doing all of the hard work:
     #
     # - Load balancing just works. Most systems have a great load balancer in
     #   'make'. If your system doesn't then just install a real 'make'.
@@ -340,23 +350,39 @@
     # basically using the filesystem as a concurrent database of test failures.
     # Even if two tests fail at the same time, since they're touching different
     # files we won't miss any failures.
-    runIndices = []
+    serialPlans = {}
+    $serialRunlist.each { |p| serialPlans[p] = nil }
+    runPlans = []
+    serialRunPlans = []
     $runlist.each {
         | plan |
         if !$remote or plan.index % $remoteHosts.length == remoteIndex
-            runIndices << plan.index
+            if serialPlans.has_key?(plan)
+                serialRunPlans << plan
+            else
+                runPlans << plan
+            end
         end
     }
-    
+
     File.open($runnerDir + "Makefile.#{remoteIndex}", "w") {
         | outp |
-        outp.puts("all: " + runIndices.map{|v| "test_done_#{v}"}.join(' '))
-        runIndices.each {
-            | index |
-            plan = $runlist[index]
-            outp.puts "test_done_#{index}:"
-            outp.puts "\tsh test_script_#{plan.index}"
+        if serialRunPlans.empty?
+            outp.puts("all: parallel")
+        else
+            serialPrereq = "test_done_#{serialRunPlans[-1].index}"
+            outp.puts("all: #{serialPrereq}")
+            prev_target = "parallel"
+            serialRunPlans.each {
+                | plan |
+                prev_target = output_target(outp, plan, [prev_target])
+            }
+        end
+        parallelTargets = runPlans.collect {
+            | plan |
+            output_target(outp, plan, [])
         }
+        outp.puts("parallel: " + parallelTargets.join(" "))
     }
 end
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to