diff --git a/src/Athletic/AthleticEvent.php b/src/Athletic/AthleticEvent.php index 1bea574..3c44f0b 100644 --- a/src/Athletic/AthleticEvent.php +++ b/src/Athletic/AthleticEvent.php @@ -92,8 +92,55 @@ private function runBenchmarks($methods) $results = array(); foreach ($methods as $methodName => $annotations) { - if (isset($annotations['iterations']) === true) { - $results[] = $this->runMethodBenchmark($methodName, $annotations); + if (substr($methodName, 0, 7) === 'perform') { + if ($annotations['dataProvider']) { + $providerMethod = $annotations['dataProvider']; + + if (!method_exists($this, $providerMethod)) { + throw new \Exception(sprintf( + 'Provider method "%s" does not exist', + $providerMethod + )); + } + + $dataSets = $this->$providerMethod(); + + if (!is_array($dataSets)) { + throw new \Exception(sprintf( + 'Data provider method "%s" must return an array', + $providerMethod + )); + } + + $refl = new \ReflectionClass($this); + $method = $refl->getMethod($methodName); + $args = $method->getParameters(); + + $newDataSets = array(); + foreach ($dataSets as $dataSet) { + $newDataSet = array(); + foreach ($dataSet as $i => $value) { + if (isset($args[$i])) { + $newDataSet[$args[$i]->name] = $value; + } + } + $newDataSets[] = $newDataSet; + } + $dataSets = $newDataSets; + + } else { + $dataSets = array( + array() + ); + } + + foreach ($dataSets as $dataSet) { + $iterationCounts = (array) $annotations['iterations']; + + foreach ($iterationCounts as $iterationCount) { + $results[] = $this->runMethodBenchmark($methodName, $dataSet, $annotations, $iterationCount); + } + } } } return $results; @@ -106,19 +153,18 @@ private function runBenchmarks($methods) * * @return MethodResults */ - private function runMethodBenchmark($method, $annotations) + private function runMethodBenchmark($method, $dataSet, $annotations, $iterationCount) { - $iterations = $annotations['iterations']; - $avgCalibration = $this->getCalibrationTime($iterations); + $avgCalibration = $this->getCalibrationTime($iterationCount, $dataSet); $results = array(); - for ($i = 0; $i < $iterations; ++$i) { + for ($i = 0; $i < $iterationCount; ++$i) { $this->setUp(); - $results[$i] = $this->timeMethod($method) - $avgCalibration; + $results[$i] = $this->timeMethod($method, $dataSet) - $avgCalibration; $this->tearDown(); } - $finalResults = $this->methodResultsFactory->create($method, $results, $iterations); + $finalResults = $this->methodResultsFactory->create($method, $results, $iterationCount, $dataSet); $this->setOptionalAnnotations($finalResults, $annotations); @@ -132,10 +178,10 @@ private function runMethodBenchmark($method, $annotations) * * @return mixed */ - private function timeMethod($method) + private function timeMethod($method, $dataSet) { $start = microtime(true); - $this->$method(); + call_user_func_array(array($this, $method), $dataSet); return microtime(true) - $start; } @@ -145,12 +191,12 @@ private function timeMethod($method) * * @return float */ - private function getCalibrationTime($iterations) + private function getCalibrationTime($iterations, $dataSet) { $emptyCalibrationMethod = 'emptyCalibrationMethod'; $resultsCalibration = array(); for ($i = 0; $i < $iterations; ++$i) { - $resultsCalibration[$i] = $this->timeMethod($emptyCalibrationMethod); + $resultsCalibration[$i] = $this->timeMethod($emptyCalibrationMethod, $dataSet); } return array_sum($resultsCalibration) / count($resultsCalibration); } @@ -177,4 +223,4 @@ private function setOptionalAnnotations(MethodResults $finalResults, $annotation } } -} \ No newline at end of file +} diff --git a/src/Athletic/Common/DICBuilder.php b/src/Athletic/Common/DICBuilder.php index 97f656d..f5a8150 100644 --- a/src/Athletic/Common/DICBuilder.php +++ b/src/Athletic/Common/DICBuilder.php @@ -115,8 +115,8 @@ private function setupMethodResults() $this->athletic['methodResultsClass'] = '\Athletic\Results\MethodResults'; $this->athletic['methodResults'] = function ($dic) { - return function ($name, $results, $iterations) use ($dic) { - return new $dic['methodResultsClass']($name, $results, $iterations); + return function ($name, $results, $iterations, $dataSet) use ($dic) { + return new $dic['methodResultsClass']($name, $results, $iterations, $dataSet); }; }; } @@ -197,4 +197,4 @@ private function setupErrorHandler() return new $dic['errorHandlerClass']($dic['command'], $dic['errorExceptionFactory']); }; } -} \ No newline at end of file +} diff --git a/src/Athletic/Factories/MethodResultsFactory.php b/src/Athletic/Factories/MethodResultsFactory.php index d71e630..833c75c 100644 --- a/src/Athletic/Factories/MethodResultsFactory.php +++ b/src/Athletic/Factories/MethodResultsFactory.php @@ -24,8 +24,8 @@ class MethodResultsFactory extends AbstractFactory * * @return MethodResults */ - public function create($name, $results, $iterations) + public function create($name, $results, $iterations, $dataSet) { - return $this->container['methodResults']($name, $results, $iterations); + return $this->container['methodResults']($name, $results, $iterations, $dataSet); } -} \ No newline at end of file +} diff --git a/src/Athletic/Formatters/DefaultFormatter.php b/src/Athletic/Formatters/DefaultFormatter.php index 6643d4f..4da2581 100644 --- a/src/Athletic/Formatters/DefaultFormatter.php +++ b/src/Athletic/Formatters/DefaultFormatter.php @@ -31,22 +31,27 @@ public function getFormattedResults($results) $returnString .= $result->getClassName() . "\n"; $longest = 0; + $longestDataSet = 0; /** @var MethodResults $methodResult */ foreach ($result as $methodResult) { - if (strlen($methodResult->methodName) > $longest) { - $longest = strlen($methodResult->methodName); + if (strlen($methodResult->getFullMethodName()) > $longest) { + $longest = strlen($methodResult->getFullMethodName()); + } + if (strlen($methodResult->getDataSetAsString()) > $longestDataSet) { + $longestDataSet = strlen($methodResult->getDataSetAsString()); } } $returnString .= ' ' . str_pad( 'Method Name', $longest - ) . " Iterations Average Time Ops/second\n"; + ) . " Iterations Average Time Ops/second\n"; - $returnString .= ' ' . str_repeat('-', $longest) . " ------------ -------------- -------------\n"; + $returnString .= ' ' . str_repeat('-', $longest) . " ------------ ---------------- -------------\n"; foreach ($result as $methodResult) { - $method = str_pad($methodResult->methodName, $longest); + $method = str_pad($methodResult->getFullMethodName(), $longest); + $iterations = str_pad(number_format($methodResult->iterations), 10); $iterations = str_pad(number_format($methodResult->iterations), 10); $avg = str_pad(number_format($methodResult->avg, 13), 13); $ops = str_pad(number_format($methodResult->ops, 5), 7); @@ -57,4 +62,4 @@ public function getFormattedResults($results) return $returnString; } -} \ No newline at end of file +} diff --git a/src/Athletic/Results/MethodResults.php b/src/Athletic/Results/MethodResults.php index f0ebc14..06ce67a 100644 --- a/src/Athletic/Results/MethodResults.php +++ b/src/Athletic/Results/MethodResults.php @@ -23,9 +23,10 @@ class MethodResults public $ops; public $group; public $baseline = false; + public $dataSet; - public function __construct($name, $results, $iterations) + public function __construct($name, $results, $iterations, $dataSet) { $this->methodName = $name; $this->results = $results; @@ -36,8 +37,22 @@ public function __construct($name, $results, $iterations) $this->min = min($results); $this->ops = ($this->sum == 0.0) ? NAN : ($iterations / $this->sum); $this->baseline = false; + $this->dataSet = $dataSet; } + public function getDataSetAsString() + { + $res = array(); + foreach ($this->dataSet as $name => $value) { + $res[] = $name . '=' . $value; + } + return implode(',', $res); + } + + public function getFullMethodName() + { + return substr($this->methodName, 7) . '(' . $this->getDataSetAsString() .')'; + } /** * @param string $group @@ -51,4 +66,4 @@ public function setBaseline() { $this->baseline = true; } -} \ No newline at end of file +}