【完全版】Pux - A High Performance PHP Routerのルーティング性能をベンチマークしてみた
Symfony routerより静的なルーティングで48.5倍、正規表現のルーティングでも31倍速いというPuxというPHPのルータに関するベンチマークのまとめです。
と続いたシリーズの最終回です。上記の記事への補足でもあります。
ベンチマーク環境
OS: Ubuntu 12.04
Apache: 2.4.7
PHP: 5.5.6 (32bit)
Phalcon: 1.2.5
Pux: 1.3.2 (C extension: 1.3.1, GitHub master 9b07e3106273a5823226051e71cca1e66628b431 Wed Jan 15 16:31:03 2014 +0800)
OrePux Basic
OrePhalconをPuxに移植したOrePuxです。
index.php:
<?php
ini_set('display_errors', 1);
error_reporting(-1);
require __DIR__ . '/../vendor/autoload.php';
$mux = new \Pux\Mux();
$mux->get('/hello/:name', ['hello','say']);
$route = $mux->dispatch($_SERVER['PATH_INFO']);
$controller = ucfirst($route[2][0]);
$action = $route[2][1];
$params = $route[3]['vars'];
try {
$controllerFilePath = __DIR__ . '/../app/controllers/' . $controller . ".php";
if (! file_exists($controllerFilePath)) {
throw new Exception("controller file is not found");
}
require $controllerFilePath;
} catch (Exception $e) {
echo $e->getMessage();
exit;
}
echo $controller::$action($params);
.htaccess:
AddDefaultCharset UTF-8
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
Hello controller
実行するHelloコントローラを用意します。
../app/controllers/Hello.php:
<?php
class Hello
{
public static function say($params)
{
return "Hello " . $params['name'];
}
}
OrePux Compiled Mux
Puxは、ルーティング情報をコンパイルすることでさらに高速化が可能です。
まず、ルーティング情報をroutes.phpに記載します。
routes.php:
<?php
require __DIR__ . '/../vendor/autoload.php';
$mux = new \Pux\Mux();
$mux->get('/hello/:name', ['hello','say']);
return $mux;
routes.phpをpuxコマンドでコンパイルします。
$ curl -O -k https://raw.github.com/c9s/Pux/master/pux
$ chmod +x pux
$ ./pux compile -o mux.php routes.php
そして、OrePuxのindex.phpをコンパイルした情報を使うように変更します。
index.php:
<?php
ini_set('display_errors', 1);
error_reporting(-1);
require __DIR__ . '/../vendor/autoload.php';
$mux = require 'mux.php';
$route = $mux->dispatch($_SERVER['PATH_INFO']);
$controller = ucfirst($route[2][0]);
$action = $route[2][1];
$params = $route[3]['vars'];
try {
$controllerFilePath = __DIR__ . '/../app/controllers/' . $controller . ".php";
if (! file_exists($controllerFilePath)) {
throw new Exception("controller file is not found");
}
require $controllerFilePath;
} catch (Exception $e) {
echo $e->getMessage();
exit;
}
echo $controller::$action($params);
OrePux Compiled Mux w/o loading autoloader
OrePhalconとのパフォーマンスの差があまりに大きいので原因を探していましたが、結論として、ComposerのAutoloaderのロードに時間がかかるためでした。
PuxのPHP機能拡張を使い、コンパイル済みのルーティング情報を使う場合は、PHP機能拡張だけで処理が可能になるため、ComposerのAutoloaderをロードする必要はありません。
そこで、OrePux Compiled Muxから以下のrequireの行を削除します。
require __DIR__ . '/../vendor/autoload.php';
ちなみに、何故、Puxを使う場合、通常はAutoloaderが必要かというと、Pux\MuxはCで実装されていますが、Pux\PatternCompilerはそうでないので、正規表現でのルーティングを使う場合は、PHPで実装されたPux\PatternCompilerをロードする必要があるためです。ルーティング情報を事前にコンパイルすることで、Pux\PatternCompilerが実行時に不要になるということのようです。
ベンチマーク
ab -n 1000 http://localhost/OrePux/web/hello/xxx
のようにベンチマークしました。
「w/o C extension」はPuxのPHP機能拡張なし、「w/z C extension」はPHP機能拡張あり、「w/o loading autoloader」はComposerのAutoloaderのロードなしです。
Framework | Requests per second | Relative |
---|---|---|
OrePux Basic w/o C extension | 318.73 | 100% |
OrePux Compiled Mux w/o C extension | 325.00 | 102% |
OrePux Basic w/z C extension | 370.68 | 116% |
OrePux Compiled Mux w/z C extension | 452.63 | 140% |
OrePux Compiled Mux w/z C extension w/o loading autoloader | 787.17 | 247% |
OrePhalcon | 801.91 | 252% |
わずかにOrePhalconの方が速いですが、大差はなくなりました。
PhalconとPHP機能拡張版のPuxのルーティング性能にそれほどの違いはないようです。
参考
Date: 2014/01/16