PHPバイトコードキャッシュの性能 – Opcache

(Last Updated On: 2018年8月13日)

PHPの性能はバイトコードキャッシュにより数倍向上するのですが、久しぶりにopcacheをキーワードに検索してみると「それほど効果がない」と誤った評価をしているページもあったので、Opcacheによりどのくらい速くなるか簡単なベンチマークをします。

テスト環境

  • CPU – Intel(R) Core(TM) i7-4770S CPU @ 3.10GHz
  • メモリ – DDR3 32GB
  • OS – Fedora 23 x86_64(4.3.4-300.fc23.x86_64)
  • Webサーバー – Fedora 23 httpd パッケージ(httpd-2.4.18-1.fc23.x86_64)
  • PHP – Fedora 23 PHP 5.6.17 パッケージ(php-5.6.17-1.fc23.x86_64)
  • Opcache – Fedora 23 Opcacheパッケージ(php-opcache-5.6.17-1.fc23.x86_64)

httpdにはサーバー名によって自動的に仮想ホストを切り換える設定がされています。これ以外の変更は特に無く、パッケージ設定以外のチューニング設定を行わないデフォルト設定を利用します。

 

テストアプリケーション

  • FuelPHP 1.7.3 のデフォルトページ

FuelPHPをインストールして最初に表示されるページを利用します。

 

ベンチマーク

abコマンドを使います。もっと高機能なツールでも良いのですがシンプルイズベストということでabコマンドにします。abコマンドもhttpdサーバーも同じPC上で実行します。Opcache有り/無しで数回実行した結果のうち中間辺りの結果を記載します。

Opcache有り

[yohgaki@dev ~]$ ab -c 100 -n 10000 http://localhost/fuel/public/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software: Apache/2.4.18
Server Hostname: localhost
Server Port: 80

Document Path: /fuel/public/
Document Length: 28814 bytes

Concurrency Level: 100
Time taken for tests: 5.770 seconds
Complete requests: 10000
Failed requests: 389
(Connect: 0, Receive: 0, Length: 389, Exceptions: 0)
Total transferred: 290459610 bytes
HTML transferred: 288139610 bytes
Requests per second: 1733.17 [#/sec] (mean)
Time per request: 57.698 [ms] (mean)
Time per request: 0.577 [ms] (mean, across all concurrent requests)
Transfer rate: 49161.74 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 3 57 9.6 56 89
Waiting: 3 57 9.6 56 89
Total: 5 57 9.6 56 90

Percentage of the requests served within a certain time (ms)
50% 56
66% 59
75% 64
80% 66
90% 71
95% 75
98% 78
99% 80
100% 90 (longest request)

Opcache無し

[yohgaki@dev ~]$ ab -c 100 -n 10000 http://localhost/fuel/public/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache/2.4.18
Server Hostname:        localhost
Server Port:            80

Document Path:          /fuel/public/
Document Length:        28814 bytes

Concurrency Level:      100
Time taken for tests:   29.329 seconds
Complete requests:      10000
Failed requests:        1042
   (Connect: 0, Receive: 0, Length: 1042, Exceptions: 0)
Total transferred:      290458831 bytes
HTML transferred:       288138831 bytes
Requests per second:    340.96 [#/sec] (mean)
Time per request:       293.285 [ms] (mean)
Time per request:       2.933 [ms] (mean, across all concurrent requests)
Transfer rate:          9671.51 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:    20  292  34.7    289     508
Waiting:       19  287  32.9    285     483
Total:         21  292  34.6    289     508

Percentage of the requests served within a certain time (ms)
  50%    289
  66%    302
  75%    311
  80%    316
  90%    332
  95%    348
  98%    374
  99%    395
 100%    508 (longest request)

 

ベンチマーク結果の評価

バイトコードキャッシュの性能を正しく評価するには幾つかのポイントがあります。

  • バイトコードキャッシュはスクリプトのコンパイル結果をキャッシュする

コンパイル結果をキャッシュするので2回目以降のリクエストでないと速くなりません。最近のOpcacheはファイルにキャッシュすることができますが、メモリにキャッシュしているとCLI/CGIの場合は速くなりません。

  • Web環境では多数の同時リクエストを想定しなければならない

Webアプリを速くしたい=沢山のアクセスがある、という場合が多いと思います。同時リクエスト数とテストで送信するリクエスト数はある程度大きな数字でないと意味のある結果を得られません。”ab -c 100 -n 10000″と実行したので同時アクセス数が100、リクエスト総数が10000になり、1クライアントあたり100回リクエストを送信した場合と同等となります。

  • リクエスト/秒のみでなく、レスポンス時間が重要である

PHPはWeb環境で利用される場合がほとんどです。単位時間あたりの処理回数も重要ですが、レスポンス時間もとても重要です。

これらのポイントを踏まえ、Opcache有り/無しを比較します。

Opcache有り Opcache無し
Requests per second 1733.17 340.96
Time per request(ms) 57.698 293.285
longest request(ms) 90 508
Time taken for tests(sec) 5.770 29.329

Opecache有りの方がかなり速いことは直ぐわかります。

  • 毎秒リクエスト数は約5倍Opcache有りが高速
  • リクエスト処理時間も約5倍Opecache有りが高速
  • 最も処理時間がかかったリクエストも約5倍Opcaeche有りが高速
  • 全体の処理時間も約5倍Opcache有りが高速

Opcache(APCでも同じ)有りと無しで性能の差が数割程度しかない、ということは普通のWebアプリではありません。一般的に数倍の差が出ます。

このテストケースの場合、データベースを利用していないのでデータベースサーバーにアクセスする時間が必要ないのでリクエスト数/処理時間に差が出やすい、と言えます。しかし、データベースサーバーを利用している場合でもPHPプログラムが高速に処理できます。これは少ないWebアプリサーバーで多くのユーザーからのリクエストを処理できることを意味します。Opcache無しなら5台のWebサーバーが必要なところが、Opcache有りなら1台のWebサーバーで十分、となるケースは普通にあります。

また、大量のアクセスがないサイトでも「リクエスト開始から完了までの時間が短い=ページ表示が速い」ので意味がない訳ではありません。

 

まとめ

まれにバイトコードキャッシュが原因でトラブル(動的にスクリプト/データを生成しているのに読み込まれないなど)に巻き込まれることもありますが、バイトコードキャッシュを導入するだけで、数倍PHPスクリプトが速く実行されることを期待できます。

動的にスクリプト/データを生成している場合、リフレッシュ期間(キャッシュの有効期限)を指定したり、キャッシュさせない設定も可能です。

APCでも十分速くなりますが、現在のPHPのバイトコードキャッシュ標準はOpcacheです。もし利用していないなら是非利用してみてください。

PHP 5.6+Opcacheでかなり高速化できることが分かったと思います。PHP7ならどうなるのか?と思うかかも知れません。あるサイトではPHP 5.6 Opecahe有りとPHP7 Opcache無しではほぼ同等の性能でした。PHP7でもOpcacheを入れると数倍高速化されます。大量のアクセスでWebアプリの性能が問題となっている場合、できるだけ早くPHP7に移行することをお勧めします!

 

 

投稿者: yohgaki