Modules

Bench_ValidColor
extends Codebench
extends Kohana_Codebench

package
Kohana/Codebench
category
Tests
author
Geert De Deckere

Class declared in MODPATH/codebench/classes/Bench/ValidColor.php on line 8.

Properties

public $description

Default value:
string(482) "Optimization for <code>Validate::color()</code>.
		 See: http://forum.kohanaphp.com/comments.php?DiscussionID=2192.

		 Note that the methods with an <em>_invalid</em> suffix contain flawed regexes and should be
		 completely discarded. I left them in here for educational purposes, and to remind myself
		 to think harder and test more thoroughly. It can't be that I only found out so late in
		 the game. For the regex explanation have a look at the forum topic mentioned earlier."

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 10000

public $subjects

Default value:
array(10) (
    0 => string(3) "aaA"
    1 => string(3) "123"
    2 => string(6) "000000"
    3 => string(7) "#123456"
    4 => string(7) "#abcdef"
    5 => string(3) "ggg"
    6 => string(4) "1234"
    7 => string(8) "#1234567"
    8 => string(5) "#000
"
    9 => string(13) "}§è!çà%$z"
)

Methods

public bench_corey_regex_1_invalid( ) (defined in Bench_ValidColor)

Source Code

public function bench_corey_regex_1_invalid($subject)
{
    return (bool) preg_match('/^#?([0-9a-f]{1,2}){3}$/iD', $subject);
}

public bench_corey_regex_2( ) (defined in Bench_ValidColor)

Source Code

public function bench_corey_regex_2($subject)
{
    return (bool) preg_match('/^#?([0-9a-f]){3}(([0-9a-f]){3})?$/iD', $subject);
}

public bench_geert_regex_1a_invalid( ) (defined in Bench_ValidColor)

Source Code

public function bench_geert_regex_1a_invalid($subject)
{
    return (bool) preg_match('/^#?(?:[0-9a-f]{1,2}+){3}$/iD', $subject);
}

public bench_geert_regex_1b_invalid( ) (defined in Bench_ValidColor)

Source Code

public function bench_geert_regex_1b_invalid($subject)
{
    return (bool) preg_match('/^#?+(?:[0-9a-f]{1,2}+){3}$/iD', $subject);
}

public bench_geert_regex_2a( ) (defined in Bench_ValidColor)

Source Code

public function bench_geert_regex_2a($subject)
{
    return (bool) preg_match('/^#?[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $subject);
}

public bench_geert_regex_2b( ) (defined in Bench_ValidColor)

Source Code

public function bench_geert_regex_2b($subject)
{
    return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $subject);
}

public bench_geert_str( ) (defined in Bench_ValidColor)

Source Code

public function bench_geert_str($subject)
{
    if ($subject[0] === '#') {
        $subject = substr($subject, 1);
    }

    $strlen = strlen($subject);
    return (($strlen === 3 OR $strlen === 6) AND ctype_xdigit($subject));
}

public bench_salathe_regex_1( ) (defined in Bench_ValidColor)

Source Code

public function bench_salathe_regex_1($subject)
{
    return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?\z/i', $subject);
}

public bench_salathe_regex_2( ) (defined in Bench_ValidColor)

Source Code

public function bench_salathe_regex_2($subject)
{
    return (bool) preg_match('/\A#?+[0-9a-f]{3}(?:[0-9a-f]{3})?\z/i', $subject);
}

public bench_salathe_str( ) (defined in Bench_ValidColor)

Source Code

public function bench_salathe_str($subject)
{
    if ($subject[0] === '#') {
        $subject = substr($subject, 1);
    }

    // true if:
    // 1. $subject is 6 or 3 chars long
    // 2. $subject contains only hexadecimal digits
    return (((isset($subject[5]) AND ! isset($subject[6])) OR ( isset($subject[2]) AND ! isset($subject[3])))
        AND ctype_xdigit($subject));
}

public __construct( ) (defined in Kohana_Codebench)

Constructor.

Return Values

  • void

Source Code

public function __construct()
{
    // Set the maximum execution time
    set_time_limit(Kohana::$config->load('codebench')->max_execution_time);
}

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');
}