diff --git a/.gitignore b/.gitignore index 3031d0b..942b7a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ vendor/ tests/coverage/ +perf/docs/ .php_cs.cache diff --git a/RoboFile.php b/RoboFile.php index 89773a7..6a032af 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -60,6 +60,16 @@ class RoboFile extends \Robo\Tasks { return $this->runTests($exec, "typical", array_merge(["--coverage-html", self::BASE_TEST."coverage"], $args)); } + /** Runs a performance evaluation. + * + * The performance of the library's basic functionality is tested against + * both IntlCodePointBreakIterator and preg_split + */ + public function perf(array $args): Result { + $execpath = realpath(self::BASE."perf/perf.php"); + return $this->taskExec("php")->arg($execpath)->args($args)->run(); + } + protected function findCoverageEngine(): string { $null = null; $code = 0; diff --git a/perf/perf.php b/perf/perf.php new file mode 100644 index 0000000..7b3ff0e --- /dev/null +++ b/perf/perf.php @@ -0,0 +1,99 @@ + ["https://html.spec.whatwg.org/", "html.html"], + 'English article on Canada' => ["https://en.wikipedia.org/wiki/Canada", "canada.html"], + 'Greek article on Greece' => ["https://el.wikipedia.org/wiki/Ελλάδα", "greece.html"], + 'Japanese article on Japan' => ["https://ja.wikipedia.org/wiki/日本", "japan.html"], +]; + +$tests = [ + 'Intl code points' => ["intl", function(string $text): int { + $t = 0; + $i = \IntlBreakIterator::createCodePointInstance(); + $i->setText($text); + foreach ($i as $o) { + $p = $i->getLastCodePoint(); + $t++; + } + return $t; + }], + 'Native code points' => ["", function(string $text): int { + $t = 0; + $pos = 0; + $eof = strlen($text); + while ($pos <= $eof) { + $p = UTF8::ord($text, $pos, $pos); + $t++; + } + return $t; + }], + 'Intl characters' => ["intl", function(string $text): int { + $t = 0; + $i = \IntlBreakIterator::createCodePointInstance(); + $i->setText($text); + foreach ($i as $b) { + $p = \IntlChar::chr($i->getLastCodePoint()); + $t++; + } + return $t; + }], + 'Native characters' => ["", function(string $text): int { + $t = 0; + $pos = 0; + $eof = strlen($text); + while ($pos <= $eof) { + $p = UTF8::get($text, $pos, $pos); + $t++; + } + return $t; + }], + 'PCRE split characters' => ["pcre", function(string $text): int { + $t = 0; + foreach (preg_split('//u', $text) as $c) { + $p = $c; + $t++; + } + return $t; + }], +]; + +if (!file_exists(__DIR__."/docs/")) { + mkdir(__DIR__."/docs/"); +} + +foreach($files as $fName => $file) { + list($url, $file) = $file; + $file = __DIR__."/docs/$file"; + if (!file_exists($file)) { + $text = file_get_contents($url); + file_put_contents($file, $text); + } else { + $text = file_get_contents($file); + } + echo "$fName:\n"; + foreach($tests as $tName => $test) { + list($req, $test) = $test; + if ($req && !extension_loaded($req)) { + continue; + } else { + echo " $tName: "; + $t = []; + for ($a = 0; $a < 5; $a++) { + $s = microtime(true); + $n = $test($text); + $t[$a] = microtime(true) - $s; + } + $t = array_sum($t) / sizeof($t); + echo number_format($t, 3)." ($n characters)\n"; + } + } +}