Modules

Bench_URLSite
extends Codebench
extends Kohana_Codebench

package
Kohana/Codebench
category
Tests
author
Geert De Deckere

Class declared in MODPATH/codebench/classes/bench/urlsite.php on line 7.

Properties

public $description

public array $grades

Grade letters with their maximum scores. Used to color the graphs.

public $loops

public $subjects

Methods

public __construct( ) (defined in Bench_URLSite)

Constructor.

Return Values

  • void

Source Code

public function __construct()
{
    foreach ($this->subjects as $subject)
    {
        // Automatically create URIs with query string and/or fragment part appended
        $this->subjects[] = $subject.'?query=string';
        $this->subjects[] = $subject.'#fragment';
        $this->subjects[] = $subject.'?query=string#fragment';
    }
 
    parent::__construct();
}

public bench_explode( ) (defined in Bench_URLSite)

Source Code

public function bench_explode($uri)
{
    // Chop off possible scheme, host, port, user and pass parts
    $path = preg_replace('~^[-a-z0-9+.]++://[^/]++/?~', '', trim($uri, '/'));
 
    $fragment = '';
    $explode = explode('#', $path, 2);
    if (isset($explode[1]))
    {
        $path = $explode[0];
        $fragment = '#'.$explode[1];
    }
 
    $query = '';
    $explode = explode('?', $path, 2);
    if (isset($explode[1]))
    {
        $path = $explode[0];
        $query = '?'.$explode[1];
    }
 
    return $path.$query.$fragment;
}

public bench_less_is_more( ) (defined in Bench_URLSite)

Source Code

public function bench_less_is_more($uri)
{
    // Chop off possible scheme, host, port, user and pass parts
    $path = preg_replace('~^[-a-z0-9+.]++://[^/]++/?~', '', trim($uri, '/'));
 
    return $path;
}

public bench_less_is_more_with_strpos_optimization( ) (defined in Bench_URLSite)

Source Code

public function bench_less_is_more_with_strpos_optimization($uri)
{
    if (strpos($uri, '://') !== FALSE)
    {
        // Chop off possible scheme, host, port, user and pass parts
        $uri = preg_replace('~^[-a-z0-9+.]++://[^/]++/?~', '', trim($uri, '/'));
    }
 
    return $uri;
}

public bench_original( ) (defined in Bench_URLSite)

Source Code

public function bench_original($uri)
{
    // Get the path from the URI
    $path = trim(parse_url($uri, PHP_URL_PATH), '/');
 
    if ($query = parse_url($uri, PHP_URL_QUERY))
    {
        $query = '?'.$query;
    }
 
    if ($fragment = parse_url($uri, PHP_URL_FRAGMENT))
    {
        $fragment = '#'.$fragment;
    }
 
    return $path.$query.$fragment;
}

public bench_regex( ) (defined in Bench_URLSite)

Source Code

public function bench_regex($uri)
{
    preg_match('~^(?:[-a-z0-9+.]++://[^/]++/?)?([^?#]++)?(\?[^#]*+)?(#.*)?~', trim($uri, '/'), $matches);
    $path = Arr::get($matches, 1, '');
    $query = Arr::get($matches, 2, '');
    $fragment = Arr::get($matches, 3, '');
 
    return $path.$query.$fragment;
}

public bench_regex_without_arrget( ) (defined in Bench_URLSite)

Source Code

public function bench_regex_without_arrget($uri)
{
    preg_match('~^(?:[-a-z0-9+.]++://[^/]++/?)?([^?#]++)?(\?[^#]*+)?(#.*)?~', trim($uri, '/'), $matches);
    $path = isset($matches[1]) ? $matches[1] : '';
    $query = isset($matches[2]) ? $matches[2] : '';
    $fragment = isset($matches[3]) ? $matches[3] : '';
 
    return $path.$query.$fragment;
}

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), array($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 = array('NULL' => NULL);
    }
 
    // Initialize benchmark output
    $codebench = array
    (
        'class'       => get_class($this),
        'description' => $this->description,
        'loops'       => array
        (
            'base'    => (int) $this->loops,
            'total'   => (int) $this->loops * count($this->subjects) * count($methods),
        ),
        'subjects'    => $this->subjects,
        'benchmarks'  => array(),
    );
 
    // Benchmark each method
    foreach ($methods as $method)
    {
        // Initialize benchmark output for this method
        $codebench['benchmarks'][$method] = array('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] = array
            (
                '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 = array('time' => 999999999, 'memory' => 999999999);
    $slowest_method = $slowest_subject = array('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');
}