Upgrade to KH 3.3.0
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_ArrCallback extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Parsing <em>command[param,param]</em> strings in <code>Arr::callback()</code>:
|
||||
http://github.com/shadowhand/kohana/commit/c3aaae849164bf92a486e29e736a265b350cb4da#L0R127';
|
||||
|
||||
public $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Valid callback strings
|
||||
'foo',
|
||||
'foo::bar',
|
||||
'foo[apple,orange]',
|
||||
'foo::bar[apple,orange]',
|
||||
'[apple,orange]', // no command, only params
|
||||
'foo[[apple],[orange]]', // params with brackets inside
|
||||
|
||||
// Invalid callback strings
|
||||
'foo[apple,orange', // no closing bracket
|
||||
);
|
||||
|
||||
public function bench_shadowhand($subject)
|
||||
{
|
||||
// The original regex we're trying to optimize
|
||||
if (preg_match('/([^\[]*+)\[(.*)\]/', $subject, $match))
|
||||
return $match;
|
||||
}
|
||||
|
||||
public function bench_geert_regex_1($subject)
|
||||
{
|
||||
// Added ^ and $ around the whole pattern
|
||||
if (preg_match('/^([^\[]*+)\[(.*)\]$/', $subject, $matches))
|
||||
return $matches;
|
||||
}
|
||||
|
||||
public function bench_geert_regex_2($subject)
|
||||
{
|
||||
// A rather experimental approach using \K which requires PCRE 7.2 ~ PHP 5.2.4
|
||||
// Note: $matches[0] = params, $matches[1] = command
|
||||
if (preg_match('/^([^\[]*+)\[\K.*(?=\]$)/', $subject, $matches))
|
||||
return $matches;
|
||||
}
|
||||
|
||||
public function bench_geert_str($subject)
|
||||
{
|
||||
// A native string function approach which beats all the regexes
|
||||
if (strpos($subject, '[') !== FALSE AND substr($subject, -1) === ']')
|
||||
return explode('[', substr($subject, 0, -1), 2);
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_AutoLinkEmails extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Fixing <a href="http://dev.kohanaphp.com/issues/2772">#2772</a>, and comparing some possibilities.';
|
||||
|
||||
public $loops = 1000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
'<ul>
|
||||
<li>voorzitter@xxxx.com</li>
|
||||
<li>vicevoorzitter@xxxx.com</li>
|
||||
</ul>',
|
||||
);
|
||||
|
||||
// The original function, with str_replace replaced by preg_replace. Looks clean.
|
||||
public function bench_match_all_loop($subject)
|
||||
{
|
||||
if (preg_match_all('~\b(?<!href="mailto:|">|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b~i', $subject, $matches))
|
||||
{
|
||||
foreach ($matches[0] as $match)
|
||||
{
|
||||
$subject = preg_replace('!\b'.preg_quote($match).'\b!', HTML::mailto($match), $subject);
|
||||
}
|
||||
}
|
||||
|
||||
return $subject;
|
||||
}
|
||||
|
||||
// The "e" stands for "eval", hmm... Ugly and slow because it needs to reinterpret the PHP code upon each match.
|
||||
public function bench_replace_e($subject)
|
||||
{
|
||||
return preg_replace(
|
||||
'~\b(?<!href="mailto:|">|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b~ie',
|
||||
'HTML::mailto("$0")', // Yuck!
|
||||
$subject
|
||||
);
|
||||
}
|
||||
|
||||
// This one should be quite okay, it just requires an otherwise useless single-purpose callback.
|
||||
public function bench_replace_callback_external($subject)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'~\b(?<!href="mailto:|">|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b~i',
|
||||
array($this, '_callback_external'),
|
||||
$subject
|
||||
);
|
||||
}
|
||||
protected function _callback_external($matches)
|
||||
{
|
||||
return HTML::mailto($matches[0]);
|
||||
}
|
||||
|
||||
// This one clearly is the ugliest, the slowest and consumes a lot of memory!
|
||||
public function bench_replace_callback_internal($subject)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'~\b(?<!href="mailto:|">|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b~i',
|
||||
create_function('$matches', 'return HTML::mailto($matches[0]);'), // Yuck!
|
||||
$subject
|
||||
);
|
||||
}
|
||||
|
||||
}
|
186
includes/kohana/modules/codebench/classes/Bench/DateSpan.php
Normal file
186
includes/kohana/modules/codebench/classes/Bench/DateSpan.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Woody Gilk <woody.gilk@kohanaphp.com>
|
||||
*/
|
||||
class Bench_DateSpan extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Optimization for <code>Date::span()</code>.';
|
||||
|
||||
public $loops = 1000;
|
||||
|
||||
public $subjects = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->subjects = array(
|
||||
time(),
|
||||
time() - Date::MONTH,
|
||||
time() - Date::YEAR,
|
||||
time() - Date::YEAR * 10,
|
||||
);
|
||||
}
|
||||
|
||||
// Original method
|
||||
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(array('deny', 'key', 'difference', 'output'));
|
||||
|
||||
// Return the difference
|
||||
$difference = array();
|
||||
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;
|
||||
}
|
||||
|
||||
// Using an array for the output
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_ExplodeLimit extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Having a look at the effect of adding a limit to the <a href="http://php.net/explode">explode</a> function.<br />
|
||||
http://stackoverflow.com/questions/1308149/how-to-get-a-part-of-url-between-4th-and-5th-slashes';
|
||||
|
||||
public $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
'http://example.com/articles/123a/view',
|
||||
'http://example.com/articles/123a/view/x/x/x/x/x',
|
||||
'http://example.com/articles/123a/view/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x',
|
||||
);
|
||||
|
||||
public function bench_explode_without_limit($subject)
|
||||
{
|
||||
$parts = explode('/', $subject);
|
||||
return $parts[4];
|
||||
}
|
||||
|
||||
public function bench_explode_with_limit($subject)
|
||||
{
|
||||
$parts = explode('/', $subject, 6);
|
||||
return $parts[4];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_GruberURL extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Optimization for http://daringfireball.net/2009/11/liberal_regex_for_matching_urls';
|
||||
|
||||
public $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
'http://foo.com/blah_blah',
|
||||
'http://foo.com/blah_blah/',
|
||||
'(Something like http://foo.com/blah_blah)',
|
||||
'http://foo.com/blah_blah_(wikipedia)',
|
||||
'(Something like http://foo.com/blah_blah_(wikipedia))',
|
||||
'http://foo.com/blah_blah.',
|
||||
'http://foo.com/blah_blah/.',
|
||||
'<http://foo.com/blah_blah>',
|
||||
'<http://foo.com/blah_blah/>',
|
||||
'http://foo.com/blah_blah,',
|
||||
'http://www.example.com/wpstyle/?p=364.',
|
||||
'http://✪df.ws/e7l',
|
||||
'rdar://1234',
|
||||
'rdar:/1234',
|
||||
'x-yojimbo-item://6303E4C1-xxxx-45A6-AB9D-3A908F59AE0E',
|
||||
'message://%3c330e7f8409726r6a4ba78dkf1fd71420c1bf6ff@mail.gmail.com%3e',
|
||||
'http://➡.ws/䨹',
|
||||
'www.➡.ws/䨹',
|
||||
'<tag>http://example.com</tag>',
|
||||
'Just a www.example.com link.',
|
||||
// To test the use of possessive quatifiers:
|
||||
'httpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp',
|
||||
);
|
||||
|
||||
public function bench_daringfireball($subject)
|
||||
{
|
||||
// Original regex by John Gruber
|
||||
preg_match('~\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))~', $subject, $matches);
|
||||
return (empty($matches)) ? FALSE : $matches[0];
|
||||
}
|
||||
|
||||
public function bench_daringfireball_v2($subject)
|
||||
{
|
||||
// Removed outer capturing parentheses, made another pair non-capturing
|
||||
preg_match('~\b(?:[\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|(?:[^[:punct:]\s]|/))~', $subject, $matches);
|
||||
return (empty($matches)) ? FALSE : $matches[0];
|
||||
}
|
||||
|
||||
public function bench_daringfireball_v3($subject)
|
||||
{
|
||||
// Made quantifiers possessive where possible
|
||||
preg_match('~\b(?:[\w-]++://?+|www[.])[^\s()<>]+(?:\([\w\d]++\)|(?:[^[:punct:]\s]|/))~', $subject, $matches);
|
||||
return (empty($matches)) ? FALSE : $matches[0];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_LtrimDigits extends Codebench {
|
||||
|
||||
public $description = 'Chopping off leading digits: regex vs ltrim.';
|
||||
|
||||
public $loops = 100000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
'123digits',
|
||||
'no-digits',
|
||||
);
|
||||
|
||||
public function bench_regex($subject)
|
||||
{
|
||||
return preg_replace('/^\d+/', '', $subject);
|
||||
}
|
||||
|
||||
public function bench_ltrim($subject)
|
||||
{
|
||||
return ltrim($subject, '0..9');
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_MDDoBaseURL extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Optimization for the <code>doBaseURL()</code> method of <code>Kohana_Kodoc_Markdown</code>
|
||||
for the Kohana Userguide.';
|
||||
|
||||
public $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Valid matches
|
||||
'[filesystem](about.filesystem)',
|
||||
'[filesystem](about.filesystem "Optional title")',
|
||||
'[same page link](#id)',
|
||||
'[object oriented](http://wikipedia.org/wiki/Object-Oriented_Programming)',
|
||||
|
||||
// Invalid matches
|
||||
'',
|
||||
'[filesystem](about.filesystem',
|
||||
);
|
||||
|
||||
public function bench_original($subject)
|
||||
{
|
||||
// The original regex contained a bug, which is fixed here for benchmarking purposes.
|
||||
// At the very start of the regex, (?!!) has been replace by (?<!!)
|
||||
return preg_replace_callback('~(?<!!)\[(.+?)\]\(([^#]\S*(?:\s*".+?")?)\)~', array($this, '_add_base_url_original'), $subject);
|
||||
}
|
||||
public function _add_base_url_original($matches)
|
||||
{
|
||||
if ($matches[2] AND strpos($matches[2], '://') === FALSE)
|
||||
{
|
||||
// Add the base url to the link URL
|
||||
$matches[2] = 'http://BASE/'.$matches[2];
|
||||
}
|
||||
|
||||
// Recreate the link
|
||||
return "[{$matches[1]}]({$matches[2]})";
|
||||
}
|
||||
|
||||
public function bench_optimized_callback($subject)
|
||||
{
|
||||
return preg_replace_callback('~(?<!!)\[(.+?)\]\((?!\w++://)([^#]\S*(?:\s*+".+?")?)\)~', array($this, '_add_base_url_optimized'), $subject);
|
||||
}
|
||||
public function _add_base_url_optimized($matches)
|
||||
{
|
||||
// Add the base url to the link URL
|
||||
$matches[2] = 'http://BASE/'.$matches[2];
|
||||
|
||||
// Recreate the link
|
||||
return "[{$matches[1]}]({$matches[2]})";
|
||||
}
|
||||
|
||||
public function bench_callback_gone($subject)
|
||||
{
|
||||
// All the optimized callback was doing now, is prepend some text to the URL.
|
||||
// We don't need a callback for that, and that should be clearly faster.
|
||||
return preg_replace('~(?<!!)(\[.+?\]\()(?!\w++://)([^#]\S*(?:\s*+".+?")?\))~', '$1http://BASE/$2', $subject);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_MDDoImageURL extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Optimization for the <code>doImageURL()</code> method of <code>Kohana_Kodoc_Markdown</code>
|
||||
for the Kohana Userguide.';
|
||||
|
||||
public $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Valid matches
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'![Alt text containing [square] brackets](img/install.png)',
|
||||
'![Empty src]()',
|
||||
|
||||
// Invalid matches
|
||||
';
|
||||
|
||||
public function bench_original($subject)
|
||||
{
|
||||
return preg_replace_callback('~!\[(.+?)\]\((\S*(?:\s*".+?")?)\)~', array($this, '_add_image_url_original'), $subject);
|
||||
}
|
||||
protected function _add_image_url_original($matches)
|
||||
{
|
||||
if ($matches[2] AND strpos($matches[2], '://') === FALSE)
|
||||
{
|
||||
// Add the base url to the link URL
|
||||
$matches[2] = 'http://BASE/'.$matches[2];
|
||||
}
|
||||
|
||||
// Recreate the link
|
||||
return "![{$matches[1]}]({$matches[2]})";
|
||||
}
|
||||
|
||||
public function bench_optimized_callback($subject)
|
||||
{
|
||||
// Moved the check for "://" to the regex, simplifying the callback function
|
||||
return preg_replace_callback('~!\[(.+?)\]\((?!\w++://)(\S*(?:\s*+".+?")?)\)~', array($this, '_add_image_url_optimized'), $subject);
|
||||
}
|
||||
protected function _add_image_url_optimized($matches)
|
||||
{
|
||||
// Add the base url to the link URL
|
||||
$matches[2] = 'http://BASE/'.$matches[2];
|
||||
|
||||
// Recreate the link
|
||||
return "![{$matches[1]}]({$matches[2]})";
|
||||
}
|
||||
|
||||
public function bench_callback_gone($subject)
|
||||
{
|
||||
// All the optimized callback was doing now, is prepend some text to the URL.
|
||||
// We don't need a callback for that, and that should be clearly faster.
|
||||
return preg_replace('~(!\[.+?\]\()(?!\w++://)(\S*(?:\s*+".+?")?\))~', '$1http://BASE/$2', $subject);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_MDDoIncludeViews extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Optimization for the <code>doIncludeViews()</code> method of <code>Kohana_Kodoc_Markdown</code>
|
||||
for the Kohana Userguide.';
|
||||
|
||||
public $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Valid matches
|
||||
'{{one}} two {{three}}',
|
||||
'{{userguide/examples/hello_world_error}}',
|
||||
|
||||
// Invalid matches
|
||||
'{}',
|
||||
'{{}}',
|
||||
'{{userguide/examples/hello_world_error}',
|
||||
'{{userguide/examples/hello_world_error }}',
|
||||
'{{userguide/examples/{{hello_world_error }}',
|
||||
);
|
||||
|
||||
public function bench_original($subject)
|
||||
{
|
||||
preg_match_all('/{{(\S+?)}}/m', $subject, $matches, PREG_SET_ORDER);
|
||||
return $matches;
|
||||
}
|
||||
|
||||
public function bench_possessive($subject)
|
||||
{
|
||||
// Using a possessive character class
|
||||
// Removed useless /m modifier
|
||||
preg_match_all('/{{([^\s{}]++)}}/', $subject, $matches, PREG_SET_ORDER);
|
||||
return $matches;
|
||||
}
|
||||
|
||||
public function bench_lookaround($subject)
|
||||
{
|
||||
// Using lookaround to move $mathes[1] into $matches[0]
|
||||
preg_match_all('/(?<={{)[^\s{}]++(?=}})/', $subject, $matches, PREG_SET_ORDER);
|
||||
return $matches;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_StripNullBytes extends Codebench {
|
||||
|
||||
public $description =
|
||||
'String replacement comparisons related to <a href="http://dev.kohanaphp.com/issues/2676">#2676</a>.';
|
||||
|
||||
public $loops = 1000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
"\0",
|
||||
"\0\0\0\0\0\0\0\0\0\0",
|
||||
"bla\0bla\0bla\0bla\0bla\0bla\0bla\0bla\0bla\0bla",
|
||||
"blablablablablablablablablablablablablablablabla",
|
||||
);
|
||||
|
||||
public function bench_str_replace($subject)
|
||||
{
|
||||
return str_replace("\0", '', $subject);
|
||||
}
|
||||
|
||||
public function bench_strtr($subject)
|
||||
{
|
||||
return strtr($subject, array("\0" => ''));
|
||||
}
|
||||
|
||||
public function bench_preg_replace($subject)
|
||||
{
|
||||
return preg_replace('~\0+~', '', $subject);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_Transliterate extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Inspired by:
|
||||
http://forum.kohanaframework.org/comments.php?DiscussionID=6113';
|
||||
|
||||
public $loops = 10;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// ASCII
|
||||
'a', 'b', 'c', 'd', '1', '2', '3',
|
||||
|
||||
// Non-ASCII
|
||||
'à', 'ô', 'ď', 'ḟ', 'ë', 'š', 'ơ',
|
||||
'ß', 'ă', 'ř', 'ț', 'ň', 'ā', 'ķ',
|
||||
'ŝ', 'ỳ', 'ņ', 'ĺ', 'ħ', 'ṗ', 'ó',
|
||||
'ú', 'ě', 'é', 'ç', 'ẁ', 'ċ', 'õ',
|
||||
'ṡ', 'ø', 'ģ', 'ŧ', 'ș', 'ė', 'ĉ',
|
||||
'ś', 'î', 'ű', 'ć', 'ę', 'ŵ', 'ṫ',
|
||||
'ū', 'č', 'ö', 'è', 'ŷ', 'ą', 'ł',
|
||||
'ų', 'ů', 'ş', 'ğ', 'ļ', 'ƒ', 'ž',
|
||||
'ẃ', 'ḃ', 'å', 'ì', 'ï', 'ḋ', 'ť',
|
||||
'ŗ', 'ä', 'í', 'ŕ', 'ê', 'ü', 'ò',
|
||||
'ē', 'ñ', 'ń', 'ĥ', 'ĝ', 'đ', 'ĵ',
|
||||
'ÿ', 'ũ', 'ŭ', 'ư', 'ţ', 'ý', 'ő',
|
||||
'â', 'ľ', 'ẅ', 'ż', 'ī', 'ã', 'ġ',
|
||||
'ṁ', 'ō', 'ĩ', 'ù', 'į', 'ź', 'á',
|
||||
'û', 'þ', 'ð', 'æ', 'µ', 'ĕ', 'ı',
|
||||
'À', 'Ô', 'Ď', 'Ḟ', 'Ë', 'Š', 'Ơ',
|
||||
'Ă', 'Ř', 'Ț', 'Ň', 'Ā', 'Ķ', 'Ĕ',
|
||||
'Ŝ', 'Ỳ', 'Ņ', 'Ĺ', 'Ħ', 'Ṗ', 'Ó',
|
||||
'Ú', 'Ě', 'É', 'Ç', 'Ẁ', 'Ċ', 'Õ',
|
||||
'Ṡ', 'Ø', 'Ģ', 'Ŧ', 'Ș', 'Ė', 'Ĉ',
|
||||
'Ś', 'Î', 'Ű', 'Ć', 'Ę', 'Ŵ', 'Ṫ',
|
||||
'Ū', 'Č', 'Ö', 'È', 'Ŷ', 'Ą', 'Ł',
|
||||
'Ų', 'Ů', 'Ş', 'Ğ', 'Ļ', 'Ƒ', 'Ž',
|
||||
'Ẃ', 'Ḃ', 'Å', 'Ì', 'Ï', 'Ḋ', 'Ť',
|
||||
'Ŗ', 'Ä', 'Í', 'Ŕ', 'Ê', 'Ü', 'Ò',
|
||||
'Ē', 'Ñ', 'Ń', 'Ĥ', 'Ĝ', 'Đ', 'Ĵ',
|
||||
'Ÿ', 'Ũ', 'Ŭ', 'Ư', 'Ţ', 'Ý', 'Ő',
|
||||
'Â', 'Ľ', 'Ẅ', 'Ż', 'Ī', 'Ã', 'Ġ',
|
||||
'Ṁ', 'Ō', 'Ĩ', 'Ù', 'Į', 'Ź', 'Á',
|
||||
'Û', 'Þ', 'Ð', 'Æ', 'İ',
|
||||
);
|
||||
|
||||
public function bench_utf8($subject)
|
||||
{
|
||||
return UTF8::transliterate_to_ascii($subject);
|
||||
}
|
||||
|
||||
public function bench_iconv($subject)
|
||||
{
|
||||
// Note: need to suppress errors on iconv because some chars trigger the following notice:
|
||||
// "Detected an illegal character in input string"
|
||||
return preg_replace('~[^-a-z0-9]+~i', '', @iconv('UTF-8', 'ASCII//TRANSLIT', $subject));
|
||||
}
|
||||
|
||||
}
|
123
includes/kohana/modules/codebench/classes/Bench/URLSite.php
Normal file
123
includes/kohana/modules/codebench/classes/Bench/URLSite.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_URLSite extends Codebench {
|
||||
|
||||
public $description = 'http://dev.kohanaframework.org/issues/3110';
|
||||
|
||||
public $loops = 1000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
'',
|
||||
'news',
|
||||
'news/',
|
||||
'/news/',
|
||||
'news/page/5',
|
||||
'news/page:5',
|
||||
'http://example.com/',
|
||||
'http://example.com/hello',
|
||||
'http://example.com:80/',
|
||||
'http://user:pass@example.com/',
|
||||
);
|
||||
|
||||
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 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 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 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 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;
|
||||
}
|
||||
|
||||
// And then I thought, why do all the work of extracting the query and fragment parts and then reappending them?
|
||||
// Just leaving them alone should be fine, right? As a bonus we get a very nice speed boost.
|
||||
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 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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Woody Gilk <woody.gilk@kohanaphp.com>
|
||||
*/
|
||||
class Bench_UserFuncArray extends Codebench {
|
||||
|
||||
public $description =
|
||||
'Testing the speed difference of using <code>call_user_func_array</code>
|
||||
compared to counting args and doing manual calls.';
|
||||
|
||||
public $loops = 100000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Argument sets
|
||||
array(),
|
||||
array('one'),
|
||||
array('one', 'two'),
|
||||
array('one', 'two', 'three'),
|
||||
);
|
||||
|
||||
public function bench_count_args($args)
|
||||
{
|
||||
$name = 'callme';
|
||||
switch (count($args))
|
||||
{
|
||||
case 1:
|
||||
$this->$name($args[0]);
|
||||
break;
|
||||
case 2:
|
||||
$this->$name($args[0], $args[1]);
|
||||
break;
|
||||
case 3:
|
||||
$this->$name($args[0], $args[1], $args[2]);
|
||||
break;
|
||||
case 4:
|
||||
$this->$name($args[0], $args[1], $args[2], $args[3]);
|
||||
break;
|
||||
default:
|
||||
call_user_func_array(array($this, $name), $args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function bench_direct_call($args)
|
||||
{
|
||||
$name = 'callme';
|
||||
call_user_func_array(array($this, $name), $args);
|
||||
}
|
||||
|
||||
protected function callme()
|
||||
{
|
||||
return count(func_get_args());
|
||||
}
|
||||
|
||||
}
|
116
includes/kohana/modules/codebench/classes/Bench/ValidColor.php
Normal file
116
includes/kohana/modules/codebench/classes/Bench/ValidColor.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_ValidColor extends Codebench {
|
||||
|
||||
public $description =
|
||||
'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 $loops = 10000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Valid colors
|
||||
'aaA',
|
||||
'123',
|
||||
'000000',
|
||||
'#123456',
|
||||
'#abcdef',
|
||||
|
||||
// Invalid colors
|
||||
'ggg',
|
||||
'1234',
|
||||
'#1234567',
|
||||
"#000\n",
|
||||
'}§è!çà%$z',
|
||||
);
|
||||
|
||||
// Note that I added the D modifier to corey's regexes. We need to match exactly
|
||||
// the same if we want the benchmarks to be of any value.
|
||||
public function bench_corey_regex_1_invalid($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?([0-9a-f]{1,2}){3}$/iD', $subject);
|
||||
}
|
||||
|
||||
public function bench_corey_regex_2($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?([0-9a-f]){3}(([0-9a-f]){3})?$/iD', $subject);
|
||||
}
|
||||
|
||||
// Optimized corey_regex_1
|
||||
// Using non-capturing parentheses and a possessive interval
|
||||
public function bench_geert_regex_1a_invalid($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?(?:[0-9a-f]{1,2}+){3}$/iD', $subject);
|
||||
}
|
||||
|
||||
// Optimized corey_regex_2
|
||||
// Removed useless parentheses, made the remaining ones non-capturing
|
||||
public function bench_geert_regex_2a($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $subject);
|
||||
}
|
||||
|
||||
// Optimized geert_regex_1a
|
||||
// Possessive "#"
|
||||
public function bench_geert_regex_1b_invalid($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?+(?:[0-9a-f]{1,2}+){3}$/iD', $subject);
|
||||
}
|
||||
|
||||
// Optimized geert_regex_2a
|
||||
// Possessive "#"
|
||||
public function bench_geert_regex_2b($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $subject);
|
||||
}
|
||||
|
||||
// Using \z instead of $
|
||||
public function bench_salathe_regex_1($subject)
|
||||
{
|
||||
return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?\z/i', $subject);
|
||||
}
|
||||
|
||||
// Using \A instead of ^
|
||||
public function bench_salathe_regex_2($subject)
|
||||
{
|
||||
return (bool) preg_match('/\A#?+[0-9a-f]{3}(?:[0-9a-f]{3})?\z/i', $subject);
|
||||
}
|
||||
|
||||
// A solution without regex
|
||||
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));
|
||||
}
|
||||
|
||||
// An ugly, but fast, solution without regex
|
||||
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));
|
||||
}
|
||||
}
|
105
includes/kohana/modules/codebench/classes/Bench/ValidURL.php
Normal file
105
includes/kohana/modules/codebench/classes/Bench/ValidURL.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* @package Kohana/Codebench
|
||||
* @category Tests
|
||||
* @author Geert De Deckere <geert@idoe.be>
|
||||
*/
|
||||
class Bench_ValidURL extends Codebench {
|
||||
|
||||
public $description =
|
||||
'filter_var vs regex:
|
||||
http://dev.kohanaframework.org/issues/2847';
|
||||
|
||||
public $loops = 1000;
|
||||
|
||||
public $subjects = array
|
||||
(
|
||||
// Valid
|
||||
'http://google.com',
|
||||
'http://google.com/',
|
||||
'http://google.com/?q=abc',
|
||||
'http://google.com/#hash',
|
||||
'http://localhost',
|
||||
'http://hello-world.pl',
|
||||
'http://hello--world.pl',
|
||||
'http://h.e.l.l.0.pl',
|
||||
'http://server.tld/get/info',
|
||||
'http://127.0.0.1',
|
||||
'http://127.0.0.1:80',
|
||||
'http://user@127.0.0.1',
|
||||
'http://user:pass@127.0.0.1',
|
||||
'ftp://my.server.com',
|
||||
'rss+xml://rss.example.com',
|
||||
|
||||
// Invalid
|
||||
'http://google.2com',
|
||||
'http://google.com?q=abc',
|
||||
'http://google.com#hash',
|
||||
'http://hello-.pl',
|
||||
'http://hel.-lo.world.pl',
|
||||
'http://ww£.google.com',
|
||||
'http://127.0.0.1234',
|
||||
'http://127.0.0.1.1',
|
||||
'http://user:@127.0.0.1',
|
||||
"http://finalnewline.com\n",
|
||||
);
|
||||
|
||||
public function bench_filter_var($url)
|
||||
{
|
||||
return (bool) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
|
||||
}
|
||||
|
||||
public function bench_regex($url)
|
||||
{
|
||||
// Based on http://www.apps.ietf.org/rfc/rfc1738.html#sec-5
|
||||
if ( ! preg_match(
|
||||
'~^
|
||||
|
||||
# scheme
|
||||
[-a-z0-9+.]++://
|
||||
|
||||
# username:password (optional)
|
||||
(?:
|
||||
[-a-z0-9$_.+!*\'(),;?&=%]++ # username
|
||||
(?::[-a-z0-9$_.+!*\'(),;?&=%]++)? # password (optional)
|
||||
@
|
||||
)?
|
||||
|
||||
(?:
|
||||
# ip address
|
||||
\d{1,3}+(?:\.\d{1,3}+){3}+
|
||||
|
||||
| # or
|
||||
|
||||
# hostname (captured)
|
||||
(
|
||||
(?!-)[-a-z0-9]{1,63}+(?<!-)
|
||||
(?:\.(?!-)[-a-z0-9]{1,63}+(?<!-)){0,126}+
|
||||
)
|
||||
)
|
||||
|
||||
# port (optional)
|
||||
(?::\d{1,5}+)?
|
||||
|
||||
# path (optional)
|
||||
(?:/.*)?
|
||||
|
||||
$~iDx', $url, $matches))
|
||||
return FALSE;
|
||||
|
||||
// We matched an IP address
|
||||
if ( ! isset($matches[1]))
|
||||
return TRUE;
|
||||
|
||||
// Check maximum length of the whole hostname
|
||||
// http://en.wikipedia.org/wiki/Domain_name#cite_note-0
|
||||
if (strlen($matches[1]) > 253)
|
||||
return FALSE;
|
||||
|
||||
// An extra check for the top level domain
|
||||
// It must start with a letter
|
||||
$tld = ltrim(substr($matches[1], (int) strrpos($matches[1], '.')), '.');
|
||||
return ctype_alpha($tld[0]);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user