Bench_DateSpan
extends Codebench
extends Kohana_Codebench
Constants
- None
Properties
Properties
-
public $description
-
Default value:
string(43) "Optimization for <code>Date::span()</code>."
-
public array $grades
-
Grade letters with their maximum scores. Used to color the graphs.
-
Default value:
array(6) ( 125 => string(1) "A" 150 => string(1) "B" 200 => string(1) "C" 300 => string(1) "D" 500 => string(1) "E" "default" => string(1) "F" )
-
public $loops
-
Default value:
integer 1000
-
public $subjects
-
Default value:
array(0)
Methods
public __construct() (defined in Bench_DateSpan)
Constructor.
Return Values
- void
Source Code
public function __construct()
{
parent::__construct();
$this->subjects = [
time(),
time() - Date::MONTH,
time() - Date::YEAR,
time() - Date::YEAR * 10,
];
}
public static bench_span_original() (defined in Bench_DateSpan)
Source Code
public static function bench_span_original($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
{
// Array with the output formats
$output = preg_split('/[^a-z]+/', strtolower( (string) $output));
// Invalid output
if (empty($output))
return FALSE;
// Make the output values into keys
extract(array_flip($output), EXTR_SKIP);
if ($local === NULL)
{
// Calculate the span from the current time
$local = time();
}
// Calculate timespan (seconds)
$timespan = abs($remote - $local);
if (isset($years))
{
$timespan -= Date::YEAR * ($years = (int) floor($timespan / Date::YEAR));
}
if (isset($months))
{
$timespan -= Date::MONTH * ($months = (int) floor($timespan / Date::MONTH));
}
if (isset($weeks))
{
$timespan -= Date::WEEK * ($weeks = (int) floor($timespan / Date::WEEK));
}
if (isset($days))
{
$timespan -= Date::DAY * ($days = (int) floor($timespan / Date::DAY));
}
if (isset($hours))
{
$timespan -= Date::HOUR * ($hours = (int) floor($timespan / Date::HOUR));
}
if (isset($minutes))
{
$timespan -= Date::MINUTE * ($minutes = (int) floor($timespan / Date::MINUTE));
}
// Seconds ago, 1
if (isset($seconds))
{
$seconds = $timespan;
}
// Remove the variables that cannot be accessed
unset($timespan, $remote, $local);
// Deny access to these variables
$deny = array_flip(['deny', 'key', 'difference', 'output']);
// Return the difference
$difference = [];
foreach ($output as $key)
{
if (isset($$key) AND ! isset($deny[$key]))
{
// Add requested key to the output
$difference[$key] = $$key;
}
}
// Invalid output formats string
if (empty($difference))
return FALSE;
// If only one output format was asked, don't put it in an array
if (count($difference) === 1)
return current($difference);
// Return array
return $difference;
}
public static bench_span_use_array() (defined in Bench_DateSpan)
Source Code
public static function bench_span_use_array($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
{
// Array with the output formats
$output = preg_split('/[^a-z]+/', strtolower( (string) $output));
// Invalid output
if (empty($output))
return FALSE;
// Convert the list of outputs to an associative array
$output = array_combine($output, array_fill(0, count($output), 0));
// Make the output values into keys
extract(array_flip($output), EXTR_SKIP);
if ($local === NULL)
{
// Calculate the span from the current time
$local = time();
}
// Calculate timespan (seconds)
$timespan = abs($remote - $local);
if (isset($output['years']))
{
$timespan -= Date::YEAR * ($output['years'] = (int) floor($timespan / Date::YEAR));
}
if (isset($output['months']))
{
$timespan -= Date::MONTH * ($output['months'] = (int) floor($timespan / Date::MONTH));
}
if (isset($output['weeks']))
{
$timespan -= Date::WEEK * ($output['weeks'] = (int) floor($timespan / Date::WEEK));
}
if (isset($output['days']))
{
$timespan -= Date::DAY * ($output['days'] = (int) floor($timespan / Date::DAY));
}
if (isset($output['hours']))
{
$timespan -= Date::HOUR * ($output['hours'] = (int) floor($timespan / Date::HOUR));
}
if (isset($output['minutes']))
{
$timespan -= Date::MINUTE * ($output['minutes'] = (int) floor($timespan / Date::MINUTE));
}
// Seconds ago, 1
if (isset($output['seconds']))
{
$output['seconds'] = $timespan;
}
if (count($output) === 1)
{
// Only a single output was requested, return it
return array_pop($output);
}
// Return array
return $output;
}
public run() (defined in Kohana_Codebench)
Runs Codebench on the extending class.
Return Values
- array - Benchmark output
Source Code
public function run()
{
// Array of all methods to loop over
$methods = array_filter(get_class_methods($this), [$this, '_method_filter']);
// Make sure the benchmark runs at least once,
// also if no subject data has been provided.
if (empty($this->subjects))
{
$this->subjects = ['NULL' => NULL];
}
// Initialize benchmark output
$codebench = [
'class' => get_class($this),
'description' => $this->description,
'loops' => [
'base' => (int) $this->loops,
'total' => (int) $this->loops * count($this->subjects) * count($methods),
],
'subjects' => $this->subjects,
'benchmarks' => [],
];
// Benchmark each method
foreach ($methods as $method)
{
// Initialize benchmark output for this method
$codebench['benchmarks'][$method] = ['time' => 0, 'memory' => 0];
// Using Reflection because simply calling $this->$method($subject) in the loop below
// results in buggy benchmark times correlating to the length of the method name.
$reflection = new ReflectionMethod(get_class($this), $method);
// Benchmark each subject on each method
foreach ($this->subjects as $subject_key => $subject)
{
// Prerun each method/subject combo before the actual benchmark loop.
// This way relatively expensive initial processes won't be benchmarked, e.g. autoloading.
// At the same time we capture the return here so we don't have to do that in the loop anymore.
$return = $reflection->invoke($this, $subject);
// Start the timer for one subject
$token = Profiler::start('codebench', $method.$subject_key);
// The heavy work
for ($i = 0; $i < $this->loops; ++$i)
{
$reflection->invoke($this, $subject);
}
// Stop and read the timer
$benchmark = Profiler::total($token);
// Benchmark output specific to the current method and subject
$codebench['benchmarks'][$method]['subjects'][$subject_key] = [
'return' => $return,
'time' => $benchmark[0],
'memory' => $benchmark[1],
];
// Update method totals
$codebench['benchmarks'][$method]['time'] += $benchmark[0];
$codebench['benchmarks'][$method]['memory'] += $benchmark[1];
}
}
// Initialize the fastest and slowest benchmarks for both methods and subjects, time and memory,
// these values will be overwritten using min() and max() later on.
// The 999999999 values look like a hack, I know, but they work,
// unless your method runs for more than 31 years or consumes over 1GB of memory.
$fastest_method = $fastest_subject = ['time' => 999999999, 'memory' => 999999999];
$slowest_method = $slowest_subject = ['time' => 0, 'memory' => 0];
// Find the fastest and slowest benchmarks, needed for the percentage calculations
foreach ($methods as $method)
{
// Update the fastest and slowest method benchmarks
$fastest_method['time'] = min($fastest_method['time'], $codebench['benchmarks'][$method]['time']);
$fastest_method['memory'] = min($fastest_method['memory'], $codebench['benchmarks'][$method]['memory']);
$slowest_method['time'] = max($slowest_method['time'], $codebench['benchmarks'][$method]['time']);
$slowest_method['memory'] = max($slowest_method['memory'], $codebench['benchmarks'][$method]['memory']);
foreach ($this->subjects as $subject_key => $subject)
{
// Update the fastest and slowest subject benchmarks
$fastest_subject['time'] = min($fastest_subject['time'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['time']);
$fastest_subject['memory'] = min($fastest_subject['memory'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['memory']);
$slowest_subject['time'] = max($slowest_subject['time'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['time']);
$slowest_subject['memory'] = max($slowest_subject['memory'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['memory']);
}
}
// Percentage calculations for methods
foreach ($codebench['benchmarks'] as & $method)
{
// Calculate percentage difference relative to fastest and slowest methods
$method['percent']['fastest']['time'] = (empty($fastest_method['time'])) ? 0 : ($method['time'] / $fastest_method['time'] * 100);
$method['percent']['fastest']['memory'] = (empty($fastest_method['memory'])) ? 0 : ($method['memory'] / $fastest_method['memory'] * 100);
$method['percent']['slowest']['time'] = (empty($slowest_method['time'])) ? 0 : ($method['time'] / $slowest_method['time'] * 100);
$method['percent']['slowest']['memory'] = (empty($slowest_method['memory'])) ? 0 : ($method['memory'] / $slowest_method['memory'] * 100);
// Assign a grade for time and memory to each method
$method['grade']['time'] = $this->_grade($method['percent']['fastest']['time']);
$method['grade']['memory'] = $this->_grade($method['percent']['fastest']['memory']);
// Percentage calculations for subjects
foreach ($method['subjects'] as & $subject)
{
// Calculate percentage difference relative to fastest and slowest subjects for this method
$subject['percent']['fastest']['time'] = (empty($fastest_subject['time'])) ? 0 : ($subject['time'] / $fastest_subject['time'] * 100);
$subject['percent']['fastest']['memory'] = (empty($fastest_subject['memory'])) ? 0 : ($subject['memory'] / $fastest_subject['memory'] * 100);
$subject['percent']['slowest']['time'] = (empty($slowest_subject['time'])) ? 0 : ($subject['time'] / $slowest_subject['time'] * 100);
$subject['percent']['slowest']['memory'] = (empty($slowest_subject['memory'])) ? 0 : ($subject['memory'] / $slowest_subject['memory'] * 100);
// Assign a grade letter for time and memory to each subject
$subject['grade']['time'] = $this->_grade($subject['percent']['fastest']['time']);
$subject['grade']['memory'] = $this->_grade($subject['percent']['fastest']['memory']);
}
}
return $codebench;
}
protected _grade(integer|double $score ) (defined in Kohana_Codebench)
Returns the applicable grade letter for a score.
Parameters
- integer|double $score required - Score
Return Values
- string - Grade letter
Source Code
protected function _grade($score)
{
foreach ($this->grades as $max => $grade)
{
if ($max === 'default')
continue;
if ($score <= $max)
return $grade;
}
return $this->grades['default'];
}
protected _method_filter(string $method ) (defined in Kohana_Codebench)
Callback for array_filter(). Filters out all methods not to benchmark.
Parameters
- string $method required - Method name
Return Values
- boolean
Source Code
protected function _method_filter($method)
{
// Only benchmark methods with the "bench" prefix
return (substr($method, 0, 5) === 'bench');
}