nette/http — pull request #35 by JanTvrdik (2014-12-18 21:59:06+00:00)
Title: RequestFactory: optimized script path detection performance

Micro-optimization.

Benchmark:
~~~php
$datasets = [
'a' => [new UrlScript('/projects/blog/www/'), '/projects/blog/www/index.php', '/projects/blog/www/'],
'b' => [new UrlScript('/projects/blog/www/contact'), '/projects/blog/www/index.php', '/projects/blog/www/'],
'c' => [new UrlScript('/projects/blog/www/index.php'), '/projects/blog/www/index.php', '/projects/blog/www/index.php'],
];

$tests = [
'old' => function ($testCount, UrlScript $url, $script, $expected) {
for ($x = 0; $x < $testCount; $x++) {
$path = strtolower($url->getPath()) . '/';
$script = strtolower($script) . '/';
$max = min(strlen($path), strlen($script));
for ($i = 0; $i < $max; $i++) {
if ($path[$i] !== $script[$i]) {
break;
} elseif ($path[$i] === '/') {
$url->setScriptPath(substr($url->getPath(), 0, $i + 1));
}
}
}
Assert::same($expected, $url->scriptPath);
},
'new' => function ($testCount, UrlScript $url, $script, $expected) {
for ($x = 0; $x < $testCount; $x++) {
$path = $url->getPath();
$max = min(strlen($path), strlen($script)) - 1;
for ($i = 0, $j = 0; $i <= $max; $i++) {
if ($path[$i] !== $script[$i] && strcasecmp($path[$i], $script[$i])) {
break;
} elseif ($path[$i] === '/') {
$j = $i;
} elseif ($i === $max) {
$j = $i + 1;
}
}
$url->setScriptPath(substr($path, 0, $j + 1));
}
Assert::same($expected, $url->scriptPath);
},
];

$testCount = 10000;
$padLength = max(array_map('strlen', array_keys($datasets))) + 3;
foreach ($tests as $testName => $testCallback) {
printf("Test %s:\n", $testName);
foreach ($datasets as $datasetName => $dataset) {
$time = -microtime(TRUE);
$testCallback($testCount, ...$dataset);
$time += microtime(TRUE);
printf(" %s%5.0f ms\n", str_pad($datasetName, $padLength), $time * 1e3);
}
printf("\n");
}
~~~

Results:
~~~
Test old:
a 1056 ms
b 1058 ms
c 1083 ms

Test new:
a 58 ms
b 60 ms
c 79 ms
~~~