JWordのO.Yです。
今回はPHP7.0とPHP5.6のパフォーマンス比較をやってみたいと思います。
前の記事ではscalaとpythonのプログラムを書いていましたが元々私はPHPらーなのであのPHPが爆速になった!!・・・と言われるとやはり興味がわきます。
PHPはphp-fpmとして起動してnginxからリクエストをunixドメインソケット経由でphp-fpmに送信し処理するようにします。
アプリケーションはEC-CUBE3.0をインストールしてトップから購入完了(セッション制御の関係上確認ページ以降にはすすめませんが)までの遷移をjmeterのプロキシサーバー機能でテスト計画を自動生成してそのテスト計画を用いてベンチマークします。
EC-CUBE3.0を使用する理由ですが私はEC系の開発をしていた時期があり、その時度々触れる機会のあったEC-CUBEはデフォルト状態で使用しても適度に重く自分で何かアプリケーションを書くよりも有用なパフォーマンステストができるだろうと判断したからです。
またバージョン3.0という最新バージョンを使用したのは新し物好きだからではなく、PHP7.0で動作するEC-CUBEはこのバージョンだけだったことも理由の一つです。
(他のバージョンはPHP7.0で動かそうとすると下位互換性の問題で動きません)
詳細なインフラ条件・ミドルウェアの条件は以下の通りです。
【ベンチマークツール】
jmeter2.12
【サーバー仕様】
Conoha(CPU6core,メモリ8G) x 3
【サーバー用途】
WEBサーバー2台、DBサーバー1台
【サーバー1(PHP7.0がインストールされたWEBサーバー)】
・PHP7.0
・php-fpm(PHP7.0)
・nginx1.0.15
・EC-CUBE3.0
【サーバー2(PHP5.6がインストールされたWEBサーバー)】
・PHP5.6
・php-fpm(PHP5.6)
・nginx1.0.15
・EC-CUBE3.0
【サーバー3(MySQLがインストールされたDBサーバー)】
・MySQL5.6
以下はPHPのコンパイルオプションとphp,php-fpm,nginxの設定です。
またMySQLに関しては設定は変更してません。
(PHP7.0とPHP5.6のコンパイルオプション)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
./configure \ --enable-mbstring \ --with-mysqli \ --with-pdo-mysql \ --with-mysqli \ --enable-pcntl \ --enable-fpm \ --with-fpm-user=nginx \ --with-fpm-group=nginx \ --with-openssl \ --with-pcre-regex \ --with-zlib \ --with-curl \ --with-mhash \ --with-mcrypt \ --with-pear \ --with-gd \ --disable-debug \ --enable-intl \ --enable-zip |
(/etc/php.iniの内容抜粋)
1 2 3 |
short_open_tag = On display_errors = On display_startup_errors = On |
(/etc/php-fpm.confの内容抜粋)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
[*] listen = /var/run/php-fpm/common.sock listen.allowed_clients = 127.0.0.1 listen.owner = nginx listen.group = nginx listen.mode = 0666 user = nginx group = nginx pm = dynamic pm.max_children = 110 pm.start_servers = 90 pm.min_spare_servers = 80 pm.max_spare_servers = 100 pm.max_requests = 500 request_terminate_timeout = 0 request_slowlog_timeout = 5 slowlog = /var/log/php-fpm/www-slow.log rlimit_files = 131072 rlimit_core = unlimited php_admin_value[error_log] = /var/log/php-fpm/error.log php_admin_flag[log_errors] = on php_admin_flag[display_erros] = off ;php_admin_value[memory_limit] = 32M php_value[max_input_vars] = 10000 php_admin_flag[display_errors] = off php_value[mbstring.language] = Japanese php_value[output_handler] = mb_output_handler php_value[mbstring.encoding_translation] = 1 php_value[upload_max_filesize] = 10M php_value[magic_quotes_gpc] = 0 |
(/etc/nginx/nginx.confの内容)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
user nginx; worker_processes 5; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; } |
(/etc/nginx/conf.d/eccube.confの内容)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
server { listen 80; server_name eccube.jword.jp; client_max_body_size 20M; access_log /var/log/nginx/eccube-access.log; error_log /var/log/nginx/eccube-error.log; root /var/www/eccube/html; index index.php; charset utf8; source_charset utf8; location / { root /var/www/eccube/html; index index.php; if (!-f $request_filename) { rewrite ^(.*)$ /index.php last; } } location ~ "(.+)\.(php|inc)" { root /var/www/eccube/html; set $script $uri; set $path_info ""; fastcgi_pass unix:/var/run/php-fpm/common.sock; include fastcgi_params; fastcgi_index index.php; fastcgi_param PATH_TRANSLATED /var/www/eccube/html$fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT /var/www/eccube/html; fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_NAME $script; } } |
server_nameにeccube.jword.jpとありますがDNS設定はしてません。
windowsのhostsファイルにipとの紐付けを記述しただけです。
(jmeterの設定)
前述しましたようにテスト計画はリバースプロキシ機能により自動生成されたものを使っています。
<<<結果>>>
それではいきなりですがベンチマークの結果を見てみましょう。
まずはPHP7.0の方からです。
平均レスポンスタイム(リクエストを開始してレスポンスデータの全てを受信するまで):959ms
平均レスポンスタイム偏差:534ms
平均レスポンスタイム(リクエストを開始してレスポンスデータの全てを受信するまで):12258ms
平均レスポンスタイム偏差:23322ms
PHP5.6はあれよあれよという間にレスポンスタイムが増加していき、最後に1分以上かかるようになってきてしまいました。
ですので途中でテストを中断し、その結果が上記となります。
PHP5.6がインストールされているサーバーでtopコマンドで各プロセスの状況を確認してみるとphp-fpmのステータスがD状態となりCPU使用率が高止まりしたままで解放されない状態となっていました。
まとめるとPHP7.0はPHP5.6と比較するとおおよそ3倍はパフォーマンスが良くしかも安定した性能を発揮できてると言えるのではないのでしょうか。
動的ページに対する大規模トラフィックを捌くには正直サーバーを増やすかキャッシュを返すかしか選択肢がなかったPHPですが、今までよりPHP7.0を使えばサーバーコストの削減になるかもしれませんね。
多分まだバグが結構あるとは思いますが、これからが楽しみなPHP7.0の紹介でした。