表題のまんま。
対象フレームワーク
- CodeIgniter 1.7.3
- ZendFramework 1.11.1
- CakePHP 1.3.6
- KohanaPHP 3.0.8
って取り終えてからsymfony抜けてるのに気付いた・・・まぁいいや。
ソース
とりあえずgithubにおいてみた
https://github.com/withgod/php_framework_benchmark
cakephpはやたらファイルが多いのでいったん保留。
git add したときに空のフォルダがすっ飛んでるのでそのままじゃ動かないかも。
実行環境
- vmware上のdebian lenny(2.6.26-2-amd64)
- 多すぎても実際に動かすサーバとの差異が出そうなので、コア2個、メモリ2G(ホストはCorei7,Mem8G)
- PHP 5.2.16-0.dotdeb.0
- Apache 2.2.9-10+lenny8
計測側は 別マシン(GigaBaseLan経由)のdebian sidからabでポチっと。
計測に使ったコードも一応晒すかと思ったんだけど、CakePHPがappsだけうまく切り離すのが面倒で良く解らなかったので止めた。
テンプレートは全部で使ってません。
#zfはzf createして出来たコードに iniでresources.frontController.noViewRenderer = 1 して Controllerで echo ‘helloworld’みたいな感じ。
計測方法
こんなシェル回すだけ、、、つって最初はかなり適当にやってたんだけど、値がおかしいので設定をもう少しつめました。
具体的には下記のような感じ。
apache
<IfModule mpm_prefork_module>
StartServers 100
MinSpareServers 100
MaxSpareServers 100
MaxClients 410
MaxRequestsPerChild 0
</IfModule>
ServerLimit 410
接続数が足りてなくてスループット出ないので変更、評価アプリが単純なのと相まって凄いスループット出てる・・・w
最初から全部400とか立ち上げるとSwapOut発生しまくりだったのでとりあえずこんな感じで。
再起動時にワーニング出るんだけど(gracefullだと駄目です、ちゃんとstop/start出来るコマンドで。してもWarningで照るんだけどね・・・)、ps axf | grep -c ‘apache2′するとちゃんと立ち上がってるみたいなので気にしない。
ulimit file descriptors
上限から変更。
/etc/security/limits.conf に次を追加
www-data hard nofile 10240
www-data soft nofile 10240
noname hard nofile 10240
noname soft nofile 10240
/etc/pam.d/login に次を追加
session required pam_limits.so
再ログインすれば有効になります、面倒なら再起動で。
上だけでも連続してテストを行うとクライアント側でTIME_WAIT、サーバ側でSYN_SENTとか溜まるので、計測取るスクリプトで sleep 90 してお茶を濁してます(確かdebian?の初期値は60秒、変更したいとなるとKernel再構築だったはず。)
計測用スクリプト
#!/bin/sh
ts=`date "+%Y%m%d%H%M%S"`
prefix='apc_'
doRun() {
ab -c 10 -n 1000 $1 > ./out/$prefix$ts-$2-010-1000.txt
sleep 90;
ab -c 30 -n 1000 $1 > ./out/$prefix$ts-$2-030-1000.txt
sleep 90;
ab -c 50 -n 1000 $1 > ./out/$prefix$ts-$2-050-1000.txt
sleep 90;
ab -c 100 -n 1000 $1 > ./out/$prefix$ts-$2-100-1000.txt
sleep 90;
ab -c 200 -n 2000 $1 > ./out/$prefix$ts-$2-200-2000.txt
sleep 90;
ab -c 300 -n 3000 $1 > ./out/$prefix$ts-$2-300-3000.txt
sleep 90;
ab -c 400 -n 4000 $1 > ./out/$prefix$ts-$2-400-4000.txt
}
doRun 'http://192.168.0.155/apps/cakephp/hello_world/' cake;
doRun 'http://192.168.0.155/apps/kohana/' kohana;
doRun 'http://192.168.0.155/apps/codeigniter/index.php/hello' ci;
doRun 'http://192.168.0.155/apps/zf/helloworld/public' zf;
doRun 'http://192.168.0.155/phpinfo' phpinfo;
何度か回してみたところ、apcなしだとcakeで300多重以上、ciで400多重以上の時にabが異常終了するので取れて無いです(サーバTAT遅延でタイムアウトするとab自体が落ちる?よーわからん)
集計用スクリプト(ログ集計+gnuplot用のスクリプト吐き出し)
ついでに↓で出してる集計につかったperlスクリプトはこんな感じ。
perlでログざーっと漁ってgnuplotへ食わすファイルに落とす、ついでにココに貼り付ける用のデータも生成。
#!/usr/bin/perl
use strict;
use Data::Dumper;
use File::Basename;
use IO::File;
use POSIX;
my $now = strftime "%Y%m%d%H%M%S", localtime;
my %data = ('apc' => {}, 'noapc' => {});
for my $f (glob './out/*.txt') {
my $b = basename($f);
my ($prefix, $target, $con, $num) = ($1, $2, $3, $4) if ($b =~ /([a-z]+)?_?\d+\-([a-z]+)\-(\d+)-(\d+)\.txt$/);
$prefix = 'noapc' unless $prefix;
$data{"$prefix"}->{$target} = {} unless (exists $data{"$prefix"}->{$target});
my $val = `grep "Requests per second" $f | awk '{print \$4}'`;
$val =~ s/[\r\n]//;
$data{"$prefix"}->{$target}->{$con} = $val;
}
for my $j (keys %data) {
print "$j\t010\t030\t050\t100\t200\t300\t400\n";
my $plot = <<"_EOT_";
set term png
set output './${now}_$j.png'
set title '$j graph'
set xlabel 'concurrency'
set ylabel 'request/per second'
set grid
plot \\
_EOT_
for my $k (keys %{$data{$j}}) {
print "$k";
my $fname = "${j}_${k}.txt";
my $fh = IO::File->new("> ./graph/${now}_$fname");
for my $l (sort keys %{$data{$j}->{$k}}) {
print "\t" . $data{$j}->{$k}->{$l} ;
print $fh $l . " " . $data{$j}->{$k}->{$l} . "\n";
}
$fh->close;
$plot .= "\"./${now}_$fname\" using 1:2 title \"$k\" with lines, \\\n";
print "\n"
}
$plot =~ s/, \\$//;
my $graph_fh = IO::File->new("> ./graph/${now}_graph_$j.plot");
print $graph_fh $plot;
$graph_fh->close;
}
計測結果
without apc

| noapc |
010 |
030 |
050 |
100 |
200 |
300 |
400 |
| kohana |
117.09 |
237.91 |
231.50 |
234.80 |
143.91 |
197.61 |
| ci |
137.77 |
203.66 |
201.19 |
201.80 |
138.70 |
| phpinfo |
137.11 |
926.16 |
932.02 |
924.78 |
489.71 |
438.99 |
342.95 |
| cake |
59.10 |
69.85 |
75.89 |
76.27 |
74.55 |
| zf |
134.77 |
907.97 |
919.69 |
931.49 |
588.52 |
435.18 |
345.51 |
with apc

| apc |
010 |
030 |
050 |
100 |
200 |
300 |
400 |
| kohana |
137.00 |
798.51 |
825.87 |
813.94 |
566.84 |
314.40 |
332.66 |
| ci |
146.27 |
807.87 |
797.76 |
803.79 |
567.05 |
381.62 |
247.43 |
| phpinfo |
131.24 |
929.17 |
915.39 |
933.95 |
588.15 |
436.91 |
342.84 |
| cake |
212.97 |
287.25 |
287.27 |
290.76 |
293.66 |
200.77 |
193.22 |
| zf |
135.00 |
900.23 |
937.48 |
937.20 |
597.30 |
437.12 |
344.20 |
所感
接続数が足りなくて最初は全然スループット出て無い。
APC入れない状態で出来てるすげー差は恐らく有効になってるモジュールの差なのかな、cakeは詰め込みまくった状態で、他は全然入ってない状態と予想。
APC入れたらその辺の差がぐっと詰まるっぽいのもそんな感じ?
入れてるapacheとかphpの設定とかはデフォルトだし、その辺を詰めてみると面白いかもしれない(ビジネスロジック部分と違ってこの辺の値は一般的に適応出来るし。 ってことでちょっと詰めてみたんだけど、凄いスループット出てる、まぁ仕方ない。)
ほんとはFrameworkの性能差が見たくてベンチ取ったんだけど、どっちかっつーとapcスゲーになった気が・・・w
あと結果に若干?な部分があるのは、他で負荷掛かってたのかなあ・・それ以外には使わない状態でやったんだけどー・・・
何度か繰り返したアベレージにしないと駄目かも(つっても接続開放とかの絡みで、1回集計に50分ぐらい掛かるからしんどい・・・w)
気が向いたらついでにvmの割り当ても変えてベンチとって見てもいいかもしれない。
zfが鬼のような値出してるけど、phpinfoと変わらない辺りを見るとなーんも入ってないに近いんだろうなあ・・・その辺は中身まで追いかけないと解らんけど、他のFWに比べてすげー緩いから具体的な部品を詰め込まないと値取れない気がする。
apc無しだと性能差が激しいけど、逆にapc入れると殆ど性能差が無いから好きなの使えって感じかなぁ(cakephpはモデル生成が走る、とかって見かけたからその辺改めて見ないと駄目かも (‘A`)
最近のコメント