メモリキャッシュやファイルキャッシュに関わらず、キャッシュで使用できる容量には上限が設定されています。 上限を設けなければ、プロセスが利用可能なリソースを食いつぶしてしまうためです。
OPCache のパラメータをチューニングするにあたり、
- キャッシュがいっぱいになった場合の挙動
- キャッシュ更新を繰り返すことで発生するフラグメンテーション(断片化)の扱い
については理解しておく必要があります。
予備知識
OPCache の挙動については、以下の記事が参考になります。
PHP OPCache, Realpath Cache and Preloading | Codana
https://www.codana.be/en/insights/php-opcache-realpath-cache-and-preloading
この記事の中で特に重要なのが、以下の点です。
OPCache はデフラグメンテーション(断片化の解消)を行わない。
キャッシュされた PHP スクリプトが更新されると、既存のキャッシュエントリは無効化されます。 しかし、そのメモリ領域は解放されるわけではなく、「wasted(無駄)」として扱われます。
そして、新しいキャッシュエントリは常にその後ろに追加されていきます。
つまり OPCache のメモリは、
- 古い領域はそのまま残る
- 新しい領域が末尾に追加される
という挙動を繰り返し、徐々に断片化していきます。
では、この断片化した領域はいつ解消されるのでしょうか。
ここで重要になるのが Memory wasted (%) です。
OPCache における Memory wasted (%) が示すもの
PHP の OPCache における Memory wasted (%) は、 OPCache が使用しているメモリのうち、現在「無効化されたキャッシュによって無駄になっている領域」の割合を示します。
この無駄なメモリは、主に以下のケースで発生します。
キャッシュのフラグメンテーション
PHP スクリプトが更新されると、既存のキャッシュは無効になります。 しかし、OPCache はその領域を即座に再利用しません。
結果として、
- 無効なキャッシュデータが残る
- 連続した空きメモリが減少する
という状態が発生します。
これがフラグメンテーションです。
キャッシュエントリの再生成
デプロイ頻度が高い環境では、
- 古いスクリプトのキャッシュが無効化される
- 新しいキャッシュが追加される
という処理が繰り返されます。
この際、破棄されたキャッシュ領域が「wasted memory」として蓄積していきます。
Memory wasted (%) の意味
この値は、opcache.memory_consumption で確保されたメモリ全体に対して、
どれだけの領域が「無効化されたキャッシュ」として存在しているかを示しています。
例えば、
Memory wasted (%) = 10%
と表示されている場合、OPCache に割り当てられたメモリのうち 10% が 断片化や無効データとして利用不能な状態にあることを意味します。
理想的には、この値は 0% に近い状態が望ましく、 値が増加し続ける場合は OPCache のメモリ効率が低下している可能性があります。
opcache.max_wasted_percentage との関係
PHP 公式ドキュメントでは、opcache.max_wasted_percentage は以下のように説明されています。
メモリが不十分な場合に、再起動がスケジュールされるまでに許される、無駄なメモリの最大の割合。
デフォルト値は 5% です。
つまり、
- Memory wasted (%) がこの値を超えると
- OPCache の再起動(restart)がスケジュールされます
この再起動によって、断片化されたメモリが解放され、キャッシュ領域が初期化されます。
まとめ
OPCache は内部でデフラグメンテーションを行わないため、 スクリプトの更新を繰り返す環境ではメモリの断片化が徐々に蓄積していきます。
Memory wasted (%) は、その断片化の進行度を示す重要な指標であり、
opcache.max_wasted_percentage を超えた場合には OPCache の再起動が発生します。
OPCache を長期間安定して運用するためには、
- wasted memory の推移を監視する
- メモリサイズ(opcache.memory_consumption)を適切に設定する
といったチューニングが重要になります。