From c260613c6f166dc25d7c3a4ed090df5c08735491 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 16 Jun 2020 11:39:03 +0200 Subject: Optimize parallel test runner startup Don't connect to each worker individually: First spawn all processes and then establish connections in any order. This avoids a ~1s wait when running on many cores. --- run-tests.php | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'run-tests.php') diff --git a/run-tests.php b/run-tests.php index 0a2f592c8c..656ba645a1 100755 --- a/run-tests.php +++ b/run-tests.php @@ -1412,7 +1412,7 @@ function run_all_tests_parallel($test_files, $env, $redir_tested) // Don't start more workers than test files. $workers = max(1, min($workers, count($test_files))); - echo "Spawning workers… "; + echo "Spawning $workers workers... "; // We use sockets rather than STDIN/STDOUT for comms because on Windows, // those can't be non-blocking for some reason. @@ -1428,6 +1428,7 @@ function run_all_tests_parallel($test_files, $env, $redir_tested) $sockUri = "tcp://$sockHost:$sockPort"; $totalFileCount = count($test_files); + $startTime = microtime(true); for ($i = 1; $i <= $workers; $i++) { $proc = proc_open( $thisPHP . ' ' . escapeshellarg($thisScript), @@ -1448,16 +1449,17 @@ function run_all_tests_parallel($test_files, $env, $redir_tested) error("Failed to spawn worker $i"); } $workerProcs[$i] = $proc; + } + for ($i = 1; $i <= $workers; $i++) { $workerSock = stream_socket_accept($listenSock, 5); if ($workerSock === false) { kill_children($workerProcs); - error("Failed to accept connection from worker $i"); + error("Failed to accept connection from worker."); } $greeting = base64_encode(serialize([ "type" => "hello", - "workerID" => $i, "GLOBALS" => $GLOBALS, "constants" => [ "INIT_DIR" => INIT_DIR, @@ -1472,29 +1474,28 @@ function run_all_tests_parallel($test_files, $env, $redir_tested) stream_set_timeout($workerSock, 5); if (fwrite($workerSock, $greeting) === false) { kill_children($workerProcs); - error("Failed to send greeting to worker $i."); + error("Failed to send greeting to worker."); } $rawReply = fgets($workerSock); if ($rawReply === false) { kill_children($workerProcs); - error("Failed to read greeting reply from worker $i."); + error("Failed to read greeting reply from worker."); } $reply = unserialize(base64_decode($rawReply)); - if (!$reply || $reply["type"] !== "hello_reply" || $reply["workerID"] !== $i) { + if (!$reply || $reply["type"] !== "hello_reply") { kill_children($workerProcs); - error("Greeting reply from worker $i unexpected or could not be decoded: '$rawReply'"); + error("Greeting reply from worker unexpected or could not be decoded: '$rawReply'"); } stream_set_timeout($workerSock, 0); stream_set_blocking($workerSock, false); - $workerSocks[$i] = $workerSock; - - echo "$i "; + $workerID = $reply["workerID"]; + $workerSocks[$workerID] = $workerSock; } - echo "… done!\n"; + printf("Done in %.2fs\n", microtime(true) - $startTime); echo "=====================================================================\n"; echo "\n"; @@ -1698,8 +1699,8 @@ function run_worker() $greeting = fgets($workerSock); $greeting = unserialize(base64_decode($greeting)) or die("Could not decode greeting\n"); - if ($greeting["type"] !== "hello" || $greeting["workerID"] !== $workerID) { - error("Unexpected greeting of type $greeting[type] and for worker $greeting[workerID]"); + if ($greeting["type"] !== "hello") { + error("Unexpected greeting of type $greeting[type]"); } set_error_handler(function ($errno, $errstr, $errfile, $errline) use ($workerSock) { -- cgit v1.2.1