[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