opcacheの基礎、バイトコードキャッシュと本番設定

opcacheとは、コンパイル済みのPHPバイトコードをメモリに保持し、次回以降のコンパイルを省いて実行を速くする仕組みです。本番では有効化しておくと体感が変わることが多い機能です。

毎回コンパイルしているのを止める

PHPはリクエストのたびにソースを読み込み、パースしてバイトコードにコンパイルし、それを実行します。opcache は、このコンパイル済みのバイトコードをメモリに保持して、次回以降のコンパイルを省く仕組みですね。つまりファイルの中身が変わらない限り、二度目からはコンパイルを丸ごとスキップできる。有効にするだけで体感が変わることも多く、本番では入れておいて損はない機能だと思います。

; php.ini
opcache.enable=1
opcache.memory_consumption=128   ; キャッシュに使うメモリ(MB)
opcache.max_accelerated_files=10000 ; キャッシュするファイル数の上限

max_accelerated_files は、プロジェクトのPHPファイル数より余裕を持たせておくのがコツですね。ここが小さいとキャッシュが溢れて効きが悪くなります。現在のファイル数は opcache_get_status で確認できます。

本番と開発で設定を分ける

一番ハマるのが validate_timestamps ですね。これはファイルの更新時刻をチェックして、変わっていればキャッシュを作り直す設定です。開発中は on にしておかないと、コードを直しても反映されずに悩むことになります。逆に本番は off にすると、更新チェックのオーバーヘッドすら省けて速くなる。ただしデプロイのたびにキャッシュを明示的にクリアする運用が前提になります。

; 開発環境
opcache.validate_timestamps=1
opcache.revalidate_freq=0   ; 毎回チェック

; 本番環境
opcache.validate_timestamps=0 ; チェックしない = デプロイ時にリセット必須

デプロイ時のリセット

validate_timestamps を切ると、新しいコードをデプロイしてもキャッシュが古いまま残ります。なので本番では、デプロイの最後に opcache をリセットする一手を必ず組み込む必要がありますね。PHP-FPM を再読み込みするか、専用のリセットを叩くかのどちらかです。ここを忘れると「デプロイしたのに反映されない」という事故になるので、自動化しておくのが安心だと思います。

// デプロイ後にキャッシュを作り直す
if (function_exists('opcache_reset')) {
    opcache_reset();
}

// 状態の確認にも使える
$status = opcache_get_status();
echo $status['opcache_statistics']['num_cached_scripts'];

まとめ

opcache はコンパイル結果をキャッシュして無駄な再コンパイルを省く、というシンプルながら効果の大きい仕組みだと思います。開発では validate_timestamps を on にして反映を優先、本番では off にして速度を優先しつつデプロイ時にリセットする。この切り分けさえ間違えなければ、扱いに困ることはほぼない気がします。まず有効化から始めてみるといいですね。

よくある質問

Q. 開発中にコードを直しても反映されません。
A. validate_timestamps が off になっている可能性が高いです。開発環境では on にしておくと、更新時刻を見てキャッシュを作り直してくれます。

Q. 本番でデプロイしても変更が反映されないのはなぜですか?
A. validate_timestamps を off にした本番では、デプロイ時に opcache_reset や PHP-FPM の再読み込みでキャッシュを明示的にクリアする必要があります。

類似投稿

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です