Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 59 additions & 13 deletions src/Athletic/AthleticEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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;
}

Expand All @@ -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);
}
Expand All @@ -177,4 +223,4 @@ private function setOptionalAnnotations(MethodResults $finalResults, $annotation
}
}

}
}
6 changes: 3 additions & 3 deletions src/Athletic/Common/DICBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
};
}
Expand Down Expand Up @@ -197,4 +197,4 @@ private function setupErrorHandler()
return new $dic['errorHandlerClass']($dic['command'], $dic['errorExceptionFactory']);
};
}
}
}
6 changes: 3 additions & 3 deletions src/Athletic/Factories/MethodResultsFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
17 changes: 11 additions & 6 deletions src/Athletic/Formatters/DefaultFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -57,4 +62,4 @@ public function getFormattedResults($results)

return $returnString;
}
}
}
19 changes: 17 additions & 2 deletions src/Athletic/Results/MethodResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -51,4 +66,4 @@ public function setBaseline()
{
$this->baseline = true;
}
}
}