[prev in list] [next in list] [prev in thread] [next in thread]
List: php-qa
Subject: [PHP-QA] com phpruntests: Added a way of distributing the tasks across processors based on the times
From: Zoe Slattery <zoe () php ! net>
Date: 2013-03-02 20:32:36
Message-ID: php-mail-63e61feb8b88cc26632ad4c90db931bf875266745 () git ! php ! net
[Download RAW message or body]
Commit: 8c104424b9d647a530f545292b7ed117fb6d57d6
Author: zoe slattery <zoe@php.net> Sat, 2 Mar 2013 20:32:36 +0000
Parents: 88dfb30b0348aff3a7989c11d4e64125d6d67deb
Branches: master
Link: http://git.php.net/?p=phpruntests.git;a=commitdiff;h=8c104424b9d647a530f545292b7ed117fb6d57d6
Log:
Added a way of distributing the tasks across processors based on the times that they \
have taken to run in a previous run. This is invoked with the command line option -g. \
Also added the command line option --log filename, if enabled this will record the \
time taken for each group and which processor it was run on. Memory usage is also \
logged but only for serial runs
Changed paths:
A src/configuration/data/task_weight_file.csv
A src/configuration/data/task_weight_file.csv_fromserial
M src/configuration/rtCommandLineOptions.php
M src/configuration/rtRuntestsConfiguration.php
M src/rtUtil.php
M src/taskScheduler/rtTaskSchedulerFile.php
M src/taskScheduler/rtTaskTestGroup.php
M src/testgroup/rtGroupConfiguration.php
M src/testgroup/rtPhpTestGroup.php
M src/testrun/rtPhpTestRun.php
M tests/rtGroupConfigurationTest.php
["diff_8c104424b9d647a530f545292b7ed117fb6d57d6.txt" (text/plain)]
diff --git a/src/configuration/data/task_weight_file.csv \
b/src/configuration/data/task_weight_file.csv new file mode 100644
index 0000000..e6d5f61
--- /dev/null
+++ b/src/configuration/data/task_weight_file.csv
@@ -0,0 +1,69 @@
+sapi/tests/:0.05
+ext/standard/tests/file/windows_links/:0.09
+ext/standard/tests/:0.12
+tests/strings/:0.26
+Zend/tests/multibyte/:0.29
+tests/run-test/:0.28
+ext/standard/tests/assert/:0.32
+ext/standard/tests/time/:0.87
+ext/standard/tests/filters/:0.55
+ext/pdo_sqlite/tests/:0.97
+ext/standard/tests/image/:1
+ext/standard/tests/streams/:1.36
+ext/fileinfo/tests/:1.33
+ext/pdo/tests/:1.43
+ext/xmlwriter/tests/:1.47
+ext/tokenizer/tests/:1.56
+ext/json/tests/:1.8
+ext/ereg/tests/:2.04
+ext/mysql/tests/:1.57
+ext/phar/tests/cache_list/:2.75
+ext/standard/tests/dir/:2.67
+ext/sqlite3/tests/:3
+ext/filter/tests/:3.49
+ext/xml/tests/:3.28
+ext/standard/tests/misc/:5
+tests/func/:7.68
+tests/lang/:8.57
+ext/zlib/tests/:8.34
+ext/reflection/tests/:7.35
+ext/session/tests/:8.75
+ext/spl/tests/:17.96
+ext/standard/tests/array/:28.74
+ext/date/tests/:34.35
+Zend/tests/:162.74
+ext/standard/tests/file/:99.67
+ext/phar/tests/:33.23
+ext/standard/tests/strings/:33.58
+ext/standard/tests/general_functions/:127.13
+ext/phar/tests/tar/:14.64
+tests/classes/:11.93
+ext/dom/tests/:8.03
+ext/mysqli/tests/:8.16
+ext/standard/tests/math/:6.69
+ext/phar/tests/zip/:6.11
+ext/posix/tests/:4.82
+ext/ctype/tests/:3.3
+sapi/cli/tests/:4.03
+ext/iconv/tests/:3.41
+ext/pcre/tests/:3.07
+tests/security/:2.51
+Zend/tests/traits/:2.55
+ext/pdo_mysql/tests/:2.32
+ext/standard/tests/network/:2.59
+tests/lang/operators/:1.88
+ext/standard/tests/class_object/:1.71
+tests/basic/:1.75
+tests/output/:1.62
+ext/standard/tests/serialize/:1.41
+ext/standard/tests/url/:1.02
+ext/xmlreader/tests/:0.81
+ext/standard/tests/mail/:0.76
+ext/libxml/tests/:0.68
+sapi/cgi/tests/:0.51
+ext/standard/tests/http/:0.33
+Zend/tests/traits/bugs/:0.34
+Zend/tests/constants/:0.14
+ext/standard/tests/file/windows_acls/:0.12
+ext/standard/tests/directory/:0.11
+ext/standard/tests/versioning/:0.08
diff --git a/src/configuration/data/task_weight_file.csv_fromserial \
b/src/configuration/data/task_weight_file.csv_fromserial new file mode 100644
index 0000000..2ddced3
--- /dev/null
+++ b/src/configuration/data/task_weight_file.csv_fromserial
@@ -0,0 +1,70 @@
+#Group weightings are just run time in seconds from a serial run
+Zend/tests/:123.59
+Zend/tests/constants/:0.29
+Zend/tests/multibyte/:0.32
+Zend/tests/traits/:2.77
+Zend/tests/traits/bugs/:0.35
+ext/ctype/tests/:4.49
+ext/date/tests/:42.11
+ext/dom/tests/:9.55
+ext/ereg/tests/:2.57
+ext/fileinfo/tests/:1.83
+ext/filter/tests/:4.15
+ext/iconv/tests/:3.79
+ext/json/tests/:2.32
+ext/libxml/tests/:0.83
+ext/mysql/tests/:2.7
+ext/mysqli/tests/:8.9
+ext/pcre/tests/:3.59
+ext/pdo/tests/:1.94
+ext/pdo_mysql/tests/:2.59
+ext/pdo_sqlite/tests/:1.2
+ext/phar/tests/:48.94
+ext/phar/tests/cache_list/:3.17
+ext/phar/tests/tar/:11.45
+ext/phar/tests/zip/:6.04
+ext/posix/tests/:5.05
+ext/reflection/tests/:8.95
+ext/session/tests/:9.83
+ext/spl/tests/:17.66
+ext/sqlite3/tests/:3.9
+ext/standard/tests/array/:24.73
+ext/standard/tests/assert/:0.41
+ext/standard/tests/:0.14
+ext/standard/tests/class_object/:2.02
+ext/standard/tests/dir/:3.34
+ext/standard/tests/directory/:0.13
+ext/standard/tests/file/:98.3
+ext/standard/tests/file/windows_acls/:0.15
+ext/standard/tests/file/windows_links/:0.14
+ext/standard/tests/filters/:0.84
+ext/standard/tests/general_functions/:19.32
+ext/standard/tests/http/:0.38
+ext/standard/tests/image/:1.22
+ext/standard/tests/mail/:0.88
+ext/standard/tests/math/:7.35
+ext/standard/tests/misc/:5.23
+ext/standard/tests/network/:2.44
+ext/standard/tests/serialize/:1.6
+ext/standard/tests/streams/:1.64
+ext/standard/tests/strings/:28.75
+ext/standard/tests/time/:0.8
+ext/standard/tests/url/:1.21
+ext/standard/tests/versioning/:0.1
+ext/tokenizer/tests/:2.32
+ext/xml/tests/:4.2
+ext/xmlreader/tests/:0.93
+ext/xmlwriter/tests/:1.97
+ext/zlib/tests/:8.45
+sapi/cgi/tests/:0.57
+sapi/cli/tests/:4.09
+sapi/tests/:0.06
+tests/basic/:1.95
+tests/classes/:10.54
+tests/func/:5.5
+tests/lang/:8.3
+tests/lang/operators/:2.15
+tests/output/:1.93
+tests/run-test/:0.38
+tests/security/:2.84
+tests/strings/:0.32
diff --git a/src/configuration/rtCommandLineOptions.php \
b/src/configuration/rtCommandLineOptions.php index 7f11481..dcb1277 100644
--- a/src/configuration/rtCommandLineOptions.php
+++ b/src/configuration/rtCommandLineOptions.php
@@ -24,6 +24,7 @@ class rtCommandLineOptions
'q', // quiet, no user interaction
'v', // verbose-mode level 1
'h', // help
+ 'g', // attempt to group tasks for parallel run
);
/**
@@ -54,7 +55,7 @@ class rtCommandLineOptions
'keep-out', // keep only out files
'keep-exp', // keep only exp files
'no-clean', // do not execute clean section
- 'debug', // do not execute clean section
+ 'debug' // extra debug info
);
/**
@@ -62,6 +63,7 @@ class rtCommandLineOptions
*/
protected $longOptionsWithArgs = array(
'mopts', // memory-options (valgrind)
+ 'log', //log to a file name
);
/**
diff --git a/src/configuration/rtRuntestsConfiguration.php \
b/src/configuration/rtRuntestsConfiguration.php index 7db80ad..16a28d7 100644
--- a/src/configuration/rtRuntestsConfiguration.php
+++ b/src/configuration/rtRuntestsConfiguration.php
@@ -22,9 +22,11 @@ abstract class rtRuntestsConfiguration
protected $settings;
protected $environmentVariables;
protected $commandLine;
- protected $operatingSystem;
-
+ protected $operatingSystem;
protected $memoryTool = null;
+ protected $taskWeightings = array();
+ const WEIGHT_FILE = "/data/task_weight_file.csv";
+
protected $settingNames = array (
@@ -60,6 +62,10 @@ abstract class rtRuntestsConfiguration
//create object to hold environment variables
$this->environmentVariables = \
rtEnvironmentVariables::getInstance($this->operatingSystem); +
+ if($this->commandLine->hasOption('z')) {
+ $this->setTaskWeightings();
+ }
}
/**
@@ -168,6 +174,17 @@ abstract class rtRuntestsConfiguration
return $this->memoryTool->getCommand();
}
+ public function setTaskWeightings() {
+ $this->taskWeightings = rtUtil::readConfigurationFile(__DIR__ \
.self::WEIGHT_FILE); + }
+
+ public function hasWeight($k) {
+ return array_key_exists($k, $this->taskWeightings);
+ }
+
+ public function getWeight($k) {
+ return $this->taskWeightings[$k];
+ }
}
?>
diff --git a/src/rtUtil.php b/src/rtUtil.php
index f7573d5..da6be7c 100644
--- a/src/rtUtil.php
+++ b/src/rtUtil.php
@@ -50,37 +50,37 @@ class rtUtil
}
- /**
- * returns a list of directories containing a phpt-file
- *
+ /**
+ * returns a list of directories containing a phpt-file
+ *
* @param $path
* @return array
- */
- public static function parseDir($path)
- {
- $list = array();
- $found = false;
- foreach (scandir($path) as $file) {
-
-
- if (substr($file, 0, 1) != '.' && $file != 'CVS') {
-
- if (is_dir($path.'/'.$file)) {
-
- $list = array_merge($list, rtUtil::parseDir($path.'/'.$file));
-
- } elseif ($found === false && strpos($file, '.phpt') !== false) {
-
- $list[] = $path.'/';
- $found = true;
- }
- }
- }
-
- return $list;
- }
-
-
+ */
+ public static function parseDir($path)
+ {
+ $list = array();
+ $found = false;
+ foreach (scandir($path) as $file) {
+
+
+ if (substr($file, 0, 1) != '.' && $file != 'CVS') {
+
+ if (is_dir($path.'/'.$file)) {
+
+ $list = array_merge($list, rtUtil::parseDir($path.'/'.$file));
+
+ } elseif ($found === false && strpos($file, '.phpt') !== false) {
+
+ $list[] = $path.'/';
+ $found = true;
+ }
+ }
+ }
+
+ return $list;
+ }
+
+
/**
* This is the original version of getDirectoryList which uses \
PhptFilterIterator
*/
@@ -109,5 +109,47 @@ class rtUtil
return array_unique($result);
}
+ /*
+ * Returns the index associated with the minimum value in an array
+ *
+ */
+ public static function getMin($a) {
+ $x = array_keys($a, min($a));
+ return $x[0];
+ }
+ /*
+ * Strip any part of the path name before one of the recognised levels
+ * TODO What happens when just running tests? This is only used to match
+ * up with a weighting table. Assume no weight will be matched.
+ * Would it be better to have some other way to check that it's being run from
+ * the root of the PHP source? Do this in rtCommandLineOptions anyway(?)
+ */
+ public static function stripPath($t) {
+ $topLevelDirectory = array("Zend", "sapi", "ext", "tests");
+ foreach($topLevelDirectory as $tld) {
+ if(preg_match("/\W{1}$tld\W{1}/", $t, $matches, PREG_OFFSET_CAPTURE)) {
+ $offset = $matches[0][1] + 1;
+ return substr($t, $offset);
+ }
+ }
+ return "";
+ }
+
+ /*
+ * Standard code to read a configuration file and return results as a key->value \
array + */
+ public static function readConfigurationFile($fileName) {
+
+ $a = array();
+ $fc = file($fileName);
+
+ foreach($fc as $line) {
+ if(substr($line, 0, 1) != '#') {
+ list($key, $value) = explode(':',trim($line));
+ $a[$key] = $value;
+ }
+ }
+ return $a;
+ }
}
?>
diff --git a/src/taskScheduler/rtTaskSchedulerFile.php \
b/src/taskScheduler/rtTaskSchedulerFile.php index dabe233..475eba6 100644
--- a/src/taskScheduler/rtTaskSchedulerFile.php
+++ b/src/taskScheduler/rtTaskSchedulerFile.php
@@ -16,6 +16,7 @@
class rtTaskSchedulerFile extends rtTaskScheduler
{
const TMP_FILE = 'taskFile';
+ const LOG_FILE = '/tmp/parallellog.csv';
protected $pidStore = array(); // stores the pids of all child-processes
protected $groupTasks = false; // are the tasks already grouped by target processor
@@ -80,6 +81,9 @@ class rtTaskSchedulerFile extends rtTaskScheduler
*/
public function run()
{
+ //clears the logfile
+ //file_put_contents(self::LOG_FILE, "");
+
if ($this->processCount == 0) {
return parent::run();
}
@@ -146,10 +150,8 @@ class rtTaskSchedulerFile extends rtTaskScheduler
if ($this->groupTasks == true) {
- foreach ($this->taskList as $cid => $list) {
-
+ foreach ($this->taskList as $cid => $list) {
for ($i=0; $i<sizeof($list); $i++) {
-
$str = serialize($list[$i])."[END]";
file_put_contents(self::TMP_FILE.$cid, $str, FILE_APPEND);
}
@@ -158,7 +160,6 @@ class rtTaskSchedulerFile extends rtTaskScheduler
} else {
for ($i=0; $i<sizeof($this->taskList); $i++) {
-
$cid = $i%$this->processCount;
$str = serialize($this->taskList[$i])."[END]";
file_put_contents(self::TMP_FILE.$cid, $str, FILE_APPEND);
@@ -213,7 +214,6 @@ class rtTaskSchedulerFile extends rtTaskScheduler
file_put_contents(self::TMP_FILE.$cid, '');
$count = 0;
foreach ($taskList as $task) {
-
$s = microtime(true);
$task = unserialize($task);
@@ -223,11 +223,16 @@ class rtTaskSchedulerFile extends rtTaskScheduler
continue;
}
-
$task->run();
$e = microtime(true);
+ //$t = round($e - $s, 2);
+
+ //$logstring = $task->getSubDirectory() . ", " .$cid . ", " . $s . ", " . $e . \
", " . $t . "\n"; +
+ //file_put_contents(self::LOG_FILE, $logstring, FILE_APPEND);
+
$taskResult = $task->getResult();
//StatusList is an array 'testname=>statusObject'
diff --git a/src/taskScheduler/rtTaskTestGroup.php \
b/src/taskScheduler/rtTaskTestGroup.php index c8a3d6b..6a2ed51 100644
--- a/src/taskScheduler/rtTaskTestGroup.php
+++ b/src/taskScheduler/rtTaskTestGroup.php
@@ -42,6 +42,10 @@ class rtTaskTestGroup extends rtTask implements rtTaskInterface
return true;
}
+ public function getSubDirectory() {
+ return $this->subDirectory;
+ }
+
}
diff --git a/src/testgroup/rtGroupConfiguration.php \
b/src/testgroup/rtGroupConfiguration.php index 95a61cb..45ada45 100644
--- a/src/testgroup/rtGroupConfiguration.php
+++ b/src/testgroup/rtGroupConfiguration.php
@@ -24,6 +24,8 @@ class rtGroupConfiguration
protected $skipFile = "";
protected $hasSkipCode = false;
+ const SKIP_FILE_NAME = "skip_group_if.inc";
+
public function __construct($directory)
{
@@ -44,7 +46,7 @@ class rtGroupConfiguration
$this->environmentVariables = $setup['ENV'];
- //Remove trailing white space and add a slash to teh directory name
+ //Remove trailing white space and add a slash to the directory name
//Will need modification if we wanted to be able to give it a list of test \
directories.
$dir = trim($setup['TESTS']);
@@ -96,15 +98,14 @@ class rtGroupConfiguration
}
public function parseConfiguration() {
- //Here insert code to read a config file from the test directory that \
determines whether the set of tests should be run
- //in parallel or not?
- $this->serialGroup = false;
-
-
+ //TODO Could insert code to read a config file from the test directory that \
determines whether the set of tests should be run + //in parallel or not.
+
//Code to read the directory skipif, run it and skip the directory
- if(file_exists($this->testDirectory. "/skip_group_if.inc")) {
+ //TODO- this makes a miniscule difference to timing.
+ if(file_exists($this->testDirectory. "/" . self::SKIP_FILE_NAME)) {
$this->hasSkipCode = true;
- $this->skipFile = $this->testDirectory."/skip_group_if.inc";
+ $this->skipFile = $this->testDirectory. "/" .self::SKIP_FILE_NAME;
}
return;
@@ -129,8 +130,8 @@ class rtGroupConfiguration
public function hasSkipCode() {
return $this->hasSkipCode;
}
- public function getSkipFile() {
-
+ public function getSkipFile() {
+
return $this->skipFile;
}
}
diff --git a/src/testgroup/rtPhpTestGroup.php b/src/testgroup/rtPhpTestGroup.php
index 900141c..da16e61 100644
--- a/src/testgroup/rtPhpTestGroup.php
+++ b/src/testgroup/rtPhpTestGroup.php
@@ -46,8 +46,7 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
}
}
- if($this->groupConfiguration->hasSkipCode()) {
-
+ if($this->groupConfiguration->hasSkipCode()) {
//If there is some 'skip' code run it to see if the tests should be \
skipped and then do nothing else
$phpCommand = $this->runConfiguration->getSetting('PhpExecutable');
@@ -58,9 +57,10 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
$runner = new rtPhpRunner($phpCommand);
$result = $runner->runphp();
-
if (preg_match('/^\s*skip\s*(.+)\s*/i', $result, $matches)) {
$this->groupResults->setSkip(true);
+ $this->groupResults->setAbsTime(microtime(true));
+ $this->groupResults->setTime(0);
}
}
@@ -73,9 +73,6 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
$redirectFromID = $this->groupConfiguration->getRedirectFromID();
foreach ($this->testFiles as $testFileName) {
- //echo "\n" .memory_get_usage() . ", setup start". $testFileName . \
"\n";
-
- //testFiles is a list of file names relative to the current working \
directory
if (!file_exists($testFileName)) {
echo rtText::get('invalidTestFileName', array($testFileName));
@@ -118,8 +115,7 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
$this->groupResults->setTestStatus($testFile->getTestName(), \
$testStatus);
}
-
- //echo "\n" .memory_get_usage() . ", setup complete". $testFileName . \
"\n"; +
}
}
}
@@ -129,6 +125,9 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
$s=microtime(true);
if (count($this->testCases) == 0) {
+ $e=microtime(true);
+ $this->groupResults->setTime($e-$s);
+ $this->groupResults->setAbsTime($e);
return;
}
@@ -151,6 +150,7 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
$this->groupResults->setTime($e-$s);
$this->groupResults->setAbsTime($e);
+
}
public function writeGroup($outType, $cid=null)
diff --git a/src/testrun/rtPhpTestRun.php b/src/testrun/rtPhpTestRun.php
index f26b1f3..59cf9b6 100644
--- a/src/testrun/rtPhpTestRun.php
+++ b/src/testrun/rtPhpTestRun.php
@@ -27,6 +27,8 @@ class rtPhpTestRun
protected $processorCount;
protected $runStartTime;
protected $skippedGroups = array();
+ protected $logFileName;
+ protected $groupTasks = false;
public function __construct($argv)
{
@@ -40,7 +42,7 @@ class rtPhpTestRun
// check the operation-system (win/unix)
$os = (substr(PHP_OS, 0, 3) == "WIN") ? 'Windows' : 'Unix';
-
+
//Configure the test environment
$this->runConfiguration = \
rtRuntestsConfiguration::getInstance($this->commandLineArguments, $os); \
$this->runConfiguration->getUserEnvironment(); @@ -71,17 +73,26 @@ class rtPhpTestRun
$this->processorCount = $this->requestedProcessorCount();
+ if($this->runConfiguration->hasCommandLineOption('log')) {
+ $this->logFileName = \
$this->runConfiguration->getCommandLineOption('log'); + \
file_put_contents($this->logFileName, ""); + }
+
+ if($this->runConfiguration->hasCommandlineOption('g')) {
+ $this->groupTasks = true;
+ }
+
/*
* Main decision point. Either we start this with a directory (or set of \
directories, in which case tests are
* run as a group (and in parallel if required) or......
*/
if ($this->runConfiguration->getSetting('TestDirectories') != null) {
-
+
$this->doGroupRuns();
-
+
} else {
-
+
/*
*... the input is a test file, or list of files and are just run as \
single tests
* and not in parallel
@@ -97,18 +108,18 @@ class rtPhpTestRun
if(count($this->redirectedTestCases) > 0) {
$this->doRedirectedRuns();
}
-
+
if(($this->numberOfSerialGroups != 0) || ($this->numberOfParallelGroups != \
0)) { $this->createRunOutput();
}
-
+
}
public function doGroupRuns() {
$subDirectories = \
$this->buildSubDirectoryList($this->runConfiguration->getSetting('TestDirectories'));
-
- //An array of group configuration objects, one for each subdirectory.
+
+ //An array of group configuration objects, one for each subdirectory.
$groupConfigurations = $this->buildGroupConfigurations($subDirectories);
@@ -134,11 +145,11 @@ class rtPhpTestRun
$parallelGroups[] = $key;
}
}
-
+
if(isset($serialGroups)) {$this->numberOfSerialGroups = \
count($serialGroups);}
-
+
$this->numberOfParallelGroups = count($parallelGroups);
-
+
$this->run_parallel_groups($parallelGroups, $groupConfigurations, \
$this->processorCount); if($this->numberOfSerialGroups > 0) {
$this->run_serial_groups($serialGroups, $groupConfigurations);
@@ -150,27 +161,33 @@ class rtPhpTestRun
public function doRedirectedRuns() {
foreach($this->redirectedTestCases as $testCase){
-
+
$groupConfig = new rtGroupConfiguration(null);
$groupConfig->parseRedirect($testCase);
-
+
$group = $groupConfig->getTestDirectory();
-
+
$this->run_serial_groups(array($group), array($group=>$groupConfig));
-
+
$this->numberOfSerialGroups++;
}
}
public function run_parallel_groups($testDirectories, $groupConfigurations, \
$processCount) {
-
- // create the task-list
+
+ //Create the task list to be executed in parallel. Either randomly or trying \
to order it. $taskList = array();
- foreach($testDirectories as $testGroup) {
- $taskList[] = new rtTaskTestGroup($this->runConfiguration, $testGroup, \
$groupConfigurations[$testGroup]); + if($this->groupTasks == false) {
+ foreach($testDirectories as $testGroup) {
+ $taskList[] = new rtTaskTestGroup($this->runConfiguration, \
$testGroup, $groupConfigurations[$testGroup]); + }
+ }else {
+ $taskList = $this->groupTasksByWeight($testDirectories, \
$groupConfigurations); +
}
+
// run the task-scheduler
$scheduler = rtTaskScheduler::getInstance();
$scheduler->setTaskList($taskList);
@@ -179,24 +196,29 @@ class rtPhpTestRun
$scheduler->run();
foreach($scheduler->getResultList() as $groupResult) {
-
- if($groupResult->isSkipGroup()) {
- $this->skippedGroups[] = $groupResult->getGroupName();
+
+ if($groupResult->isSkipGroup()) {
+ $this->skippedGroups[] = $groupResult->getGroupName();
} else {
$this->resultList[] = $groupResult->getTestStatusList();
}
- // Debug - get which group was run by which processor and how long each \
took
- //
+ // Logging - get which group was run by which processor and how long \
each took
- if($this->runConfiguration->hasCommandLineOption('debug')) {
- $time = round($groupResult->getTime(), 2);
+ if($this->runConfiguration->hasCommandLineOption('log')) {
- $absTime = $groupResult->getAbsTime() - $this->runStartTime;
+ $groupTime = round($groupResult->getTime(), 2);
+ $runTime = $groupResult->getAbsTime() - $this->runStartTime;
+
+ $runTime = round($runTime, 2);
- $absTime = round($absTime, 2);
+ $string = "PARLOG," . $groupResult->getGroupName() .
+ "," . $groupTime .
+ "," . $runTime .
+ "," . $groupResult->getProcessorId() .
+ "," . $groupResult->getRunOrder() ."\n";
- echo "\nPARDBG," . $absTime. "," . $time . "," . \
$groupResult->getProcessorId() . "," . $groupResult->getRunOrder() . "," . \
$groupResult->getGroupName(); + file_put_contents($this->logFileName, \
$string, FILE_APPEND);
}
@@ -212,68 +234,61 @@ class rtPhpTestRun
public function run_serial_groups($testDirectories, $groupConfigurations) {
- $count = 0;
-
- foreach($testDirectories as $subDirectory) {
+ $groupCount = 0;
- // Memory usage debugging
- //$startm = memory_get_usage();
+ foreach($testDirectories as $subDirectory) {
-
+ // Memory usage logging
+ $startMemory = memory_get_usage();
$testGroup = new rtPhpTestGroup($this->runConfiguration, $subDirectory, \
$groupConfigurations[$subDirectory]);
-
-
- if($testGroup->isSkipGroup() == true) {
+
+
+ if($testGroup->isSkipGroup() === true) {
$this->skippedGroups[] = $testGroup->getGroupName();
- } else {
-
+ continue;
+ }
- $testGroup->run();
-
-
- // Memory usage debugging
- //$midm = memory_get_usage();
+ $testGroup->run();
- rtTestOutputWriter::flushResult($testGroup->getGroupResults()->getTestStatusList(), \
$this->reportStatus);
- $this->resultList[] = \
$testGroup->getGroupResults()->getTestStatusList(); + \
rtTestOutputWriter::flushResult($testGroup->getGroupResults()->getTestStatusList(), \
$this->reportStatus); + $this->resultList[] = \
$testGroup->getGroupResults()->getTestStatusList(); +
+ if($this->runConfiguration->hasCommandLineOption('log')) {
- if($this->runConfiguration->hasCommandLineOption('debug')) {
-
- $time = round($testGroup->getGroupResults()->getTime(), 2);
+ $time = round($testGroup->getGroupResults()->getTime(), 2);
- $absTime = ($testGroup->getGroupResults()->getAbsTime()) - \
$this->runStartTime;
- $absTime = round($absTime, 2);
+ $absTime = ($testGroup->getGroupResults()->getAbsTime()) - \
$this->runStartTime; +
+ $absTime = round($absTime, 2);
+
+ $string = "SERLOG," . $testGroup->getGroupName() . "," .
+ $time . "," .
+ $absTime . "," .
+ $testGroup->getGroupResults()->getProcessorId() . "," .
+ $groupCount . "\n";
- echo "\nSERDBG," . $absTime . "," . $time . "," . \
$testGroup->getGroupResults()->getProcessorId() . "," . $count . "," . \
$testGroup->getGroupResults()->getGroupName(); + \
file_put_contents($this->logFileName, $string, FILE_APPEND);
- }
-
- // Memory usage debugging
- //$midm2 = memory_get_usage();
-
- $redirects = \
$testGroup->getGroupResults()->getRedirectedTestCases();
- foreach($redirects as $testCase) {
- $this->redirectedTestCases[] = $testCase;
- }
-
-
-
- // Memory usage debugging
- //$midm3 = memory_get_usage();
-
-
- $testGroup->__destruct();
- unset($testGroup);
-
- // Memory usage debugging
- //echo "\n" . $startm . ", " . $midm. ", " .$midm2. ", " .$midm3. ", \
" .memory_get_usage() . ", ". $subDirectory . "\n";
- $count++;
}
- }
+
+ $redirects = $testGroup->getGroupResults()->getRedirectedTestCases();
+ foreach($redirects as $testCase) {
+ $this->redirectedTestCases[] = $testCase;
+ }
- //xdebug_stop_trace();
+
+ $testGroup->__destruct();
+ unset($testGroup);
+
+ if($this->runConfiguration->hasCommandLineOption('log')) {
+ $string = "MEMLOG," . $subDirectory . ", " . $startMemory. ", " \
.memory_get_usage() . "\n"; + file_put_contents($this->logFileName, \
$string, FILE_APPEND); + }
+
+ $groupCount++;
+ }
}
public function run_tests($testNames) {
@@ -286,19 +301,19 @@ class rtPhpTestRun
echo rtText::get('invalidTestFileName', array($testName));
exit();
}
-
-
+
+
//Read the test file
$testFile = new rtPhpTestFile();
$testFile->doRead($testName);
$testFile->normaliseLineEndings();
-
+
$testStatus = new rtTestStatus($testFile->getTestName());
if ($testFile->arePreconditionsMet()) {
$testCase = new rtPhpTest($testFile->getContents(), \
$testFile->getTestName(), $testFile->getSectionHeadings(), $this->runConfiguration, \
$testStatus);
-
+
//Setup and set the local environment for the test case
$testCase->executeTest($this->runConfiguration);
@@ -307,12 +322,12 @@ class rtPhpTestRun
$summaryResults = array($testFile->getTestName() => \
$results->getStatus());
} elseif (in_array("REDIRECTTEST", $testFile->getSectionHeadings())) {
-
+
//Redirect handler
//Build a list of redirected test cases
-
+
$this->redirectedTestCases[] = new \
rtPhpTest($testFile->getContents(), $testFile->getTestName(), \
$testFile->getSectionHeadings(), $this->runConfiguration, \
$testStatus);
-
+
$testStatus->setTrue('redirected');
$testStatus->setMessage('redirected', $testFile->getExitMessage());
$summaryResults = array($testFile->getTestName() => $testStatus);
@@ -324,7 +339,7 @@ class rtPhpTestRun
}
rtTestOutputWriter::flushResult($summaryResults, 3);
-
+
}
}
@@ -419,6 +434,55 @@ class rtPhpTestRun
}
return $groupSummary;
}
+ /*
+ * This, invoked by using the -g command line option,
+ * makes an attempt to distribute tests evenly across the processors
+ * based on 'weightings'. The weightings are actually just timings from a \
previous + * parallel run.
+ */
+ public function groupTasksByWeight($testDirectories, $groupConfigurations) {
+
+ //First set weights.
+ $weightedDirectoryList = array();
+ $processorWeightSum = array();
+ $taskListByProcessor = array();
+
+ foreach($testDirectories as $subDir) {
+ $key = rtUtil::stripPath($subDir);
+ if($this->runConfiguration->hasWeight($key)) {
+ $weightedDirectoryList[$subDir] = \
$this->runConfiguration->getWeight($key); + } else {
+ $weightedDirectoryList[$subDir] = 1;
+ }
+ }
+
+ //Order subditrectories by decreasing weight.
+ arsort($weightedDirectoryList, SORT_NUMERIC);
+
+ //Assign the first n tasks across n processors. Having ordered the tasls \
these will be the longest running tasks + for($i=0; $i<$this->processorCount; \
$i++) { + list($key, $value) = each($weightedDirectoryList);
+ $processorWeightSum[$i] =$value;
+ $task = new rtTaskTestGroup($this->runConfiguration, $key, \
$groupConfigurations[$key]); + $taskListByProcessor[$i] = array($task);
+ }
+ //Continue to assign tasks to processors based on an estimate of how long \
each one will take. + for ($i=$this->processorCount; \
$i<count($weightedDirectoryList); $i++) { + list($key, $value) = \
each($weightedDirectoryList); + $procID = \
rtUtil::getMin($processorWeightSum); + $processorWeightSum[$procID] += \
$value; + $task = new rtTaskTestGroup($this->runConfiguration, $key, \
$groupConfigurations[$key]); + array_push($taskListByProcessor[$procID], \
$task); + }
+
+ //Reverse the order of even numbered lists so that not all processors are \
runnung big tasks at the same time + //This seems to work better - possibly \
the longer running tasks are resource constrined by something other than CPU? + \
for($i=0; $i<$this->processorCount; $i+=2) { + \
$taskListByProcessor[$procID] = array_reverse($taskListByProcessor[$procID]); + \
} +
+ return $taskListByProcessor;
+ }
}
?>
diff --git a/tests/rtGroupConfigurationTest.php b/tests/rtGroupConfigurationTest.php
index 7d4d6cd..def901b 100644
--- a/tests/rtGroupConfigurationTest.php
+++ b/tests/rtGroupConfigurationTest.php
@@ -8,12 +8,12 @@ class rtGroupConfigurationTest extends PHPUnit_Framework_TestCase
protected $path_to_group;
public function setUp() {
- $this->path_to_group = realpath(dirname(__FILE__) . \
'/../phpt-tests/group_of_tests'); + $this->path_to_group = \
realpath(dirname(__FILE__) . '/../phpt-tests/group_of_tests/'); }
public function testCreateInstance()
{
- $config = rtRuntestsConfiguration::getInstance(array('run-tests.php', '-p', \
RT_PHP_PATH, 'testgroup')); + $config = \
rtRuntestsConfiguration::getInstance(array('run-tests.php', '-p', RT_PHP_PATH, \
$this->path_to_group));
$config->configure();
--
PHP Quality Assurance Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic