...

PHP Opcacheの断片化を検知・解消し、パフォーマンスを最大化

OPcacheの断片化は、キャッシュが空きメモリを小さな断片に分割してしまうため、新しいバイトコードブロックの受け入れ効率が低下し、PHPアプリケーションの動作を目に見えて遅くします。ここでは、その対処法をご紹介します。 フラグメンテーション 確実に特定し、的確に解消し、適切なデプロイとOPcacheの設定によって恒久的に防止します。.

中心点

以下の重要なポイントを押さえることで、段階的に実行できる手っ取り早いロードマップが得られ、それによって パフォーマンス 安定させる。.

  • 主な数字 読み取り:used/free/wasted_memory、current_wasted_percentage、opcache_hit_rate。.
  • しきい値 設定:wasted_memory < 5 の場合は %、15~30 の場合は % で対応する。.
  • 構成 強化する項目:memory_consumption、max_accelerated_files、interned_strings_buffer。.
  • リセット- 戦略:opcache_reset() を予定通り実行するか、ウォームアップを伴うサービスの再起動を行う。.
  • デプロイ-分野:安定したパス、制御された無効化、モニタリング。.

OPcacheの断片化が生じる理由

OPcacheは、コンパイル済みのバイトコードを 共有 メモリは限られているが、頻繁なデプロイ、ディレクトリの変更、あるいは多数のプラグインの切り替えにより、空き領域が断片化してしまう。こうした断片化された領域は連続したブロックとして利用できないため、キャッシュの効率が低下し、バイトコードの再コンパイルが頻繁に行われることになる。 再検証間隔が短すぎると、無効化の頻度が高まり、断片化したメモリブロックの傾向がさらに悪化します。メモリやファイルインデックスの制限が低すぎると、エヴィクションが増加し、不安定なメモリレイアウトを招きます。 私はまずデプロイの習慣を確認し、パスを一定に保つようにしています。そうしないと、 フラグメンテーション リリースごとにさらに進化しています。.

OPcacheの適切な指標を読み解く

私は定期的に used_memory、free_memory、wasted_memory を分析しています。なぜなら、これらの数値が実際の キャッシュ-の品質を示す。特に重要なのは current_wasted_percentage であり、このパーセンテージ値は固定のしきい値と結びつけやすい。opcache_hit_rate が 99 % を著しく下回った場合、その傾向は未活用の潜在能力や断片化を示唆している。 さらに、ファイルエントリの制限がボトルネックを引き起こしていないかを確認するために、`num_cached_scripts`も注視しています。これらのメトリクスなしでは、変動が激しい状況下で手探りの状態になってしまいます。 パフォーマンス 暗闇の中で。.

どのような閾値に達したら対応する必要があるか

5 % wasted_memory 以下であれば、OPcache は通常目立たず動作するため、私は 設定 ひとまず。15 %に達した時点で、特にfree_memoryも同時に不足し始めた場合は、対策を講じる予定だ。遅くともwasted_memoryが30 %に達した時点で、キャッシュは事実上縮小されたものとみなされ、リセットまたは再起動を実行する。 free_memoryが約10 %まで低下し、キャッシュが満杯と報告されると、フラグメンテーションの悪化が加速します。このような閾値があることで、判断が明確になります。なぜなら、それらは アクション 「直感」ではなく、無理やり押し通す。.

実稼働時の症状を確実に判断する

多くのエンドポイントで一様にレイテンシが増加していることは、広範囲に作用する ブレーキ フラグメンテーションなど。トラフィック量が同じにもかかわらずCPU負荷が上昇していることも、キャッシュが断片化しているために再コンパイルが頻繁に行われていることと一致します。ウォームアップ後もヒット率が低いままであることは、この傾向をさらに裏付けています。 コードに大きな変更がないにもかかわらず、OPcacheの再起動やエヴィクションが頻繁に発生する場合は、キャッシュ内に連続したブロックを格納するスペースが単純に不足していることになります。私はこれらの兆候をメトリクスと照合し、その後、的を絞った 対策 より。

OPcache を確実に監視・読み取る

opcache_get_status() を使った小さなスクリプトで、必要な情報を取得できます データ PHPから直接。簡単な確認にはphpinfo()を使いますが、傾向分析のためには定期的に値をモニタリングシステムに保存しています。 wasted_memory、ヒット率、free_memoryを可視化することで、徐々に進行するパフォーマンスの低下に気づきやすくしています。デプロイ後の経時的な比較を行うことで、特定のリリースパターンがメモリの断片化を加速させているかどうかがわかります。この推移を把握しなければ、原因を特定するのは困難です カテゴライズ.

設定:ストレージとファイルの制限を明確に設定する

opcache.memory_consumption を使って、 メモリ コードベースに合わせて:小規模なWordPressサイトでは128~256 MBで十分ですが、中規模サイトでは256~384 MB、大規模なオンラインショップでは384~512 MB以上が必要となります。 opcache.max_accelerated_files を設定することで、ファイルインデックスの数が少なすぎてキャッシュ率が低下するのを防ぎます。小規模なWordPressサイトでは8000~10000、WooCommerceや大規模なフレームワークでは20000以上が実証済みです。 私はベンダーファイルを含めたPHPファイルの数を数え、その数値の1.3~1.5倍を上限に設定しています。さらに詳しく知りたい方は、以下の背景情報をご覧ください。 OPcacheの設定 実践的なガイドの中で。堅牢なリミットはメモリレイアウトを安定させ、 フラグメンテーション 目につく。

「Interned Strings」と「Huge Code Pages」の利用

opcache.interned_strings_buffer を使用することで、重複を最小限に抑えています ストリングス メモリ内;16~32 MBのバッファがあれば、大規模なプロジェクトにおいてメモリ空間をより効率的に活用できます。トラフィックの多い環境では、さらに大きなバッファを設定することでメリットが得られることがよくあります。 オプションとして、システムが大きなページを提供している場合、opcache.huge_code_pages が実行速度を向上させます。管理オーバーヘッドが少なくなれば、通常はレイテンシが若干低下し、断片化も減少する傾向があります。私は、テスト実行を経てからこのオプションを有効にします。そうすることで、 サプライズ 操業中に発生する。.

タイムスタンプの検証と再検証を正しく設定する

過度に厳格なタイムスタンプチェックは、バイトコードを無効にするケースが多く、その結果、 フラグメンテーション 高く設定します。開発環境では、変更が即座に反映されるよう、validate_timestamps=1とし、revalidate_freqを低く設定しています。本番環境では、60~300秒という適度な間隔を選択するか、validate_timestamps=0に設定し、リリース時にOPcacheを明示的にリセットするようにしています。 原因をさらに深く調査したい場合は、分析機能を利用して OPcacheの検証 および発生しうるパフォーマンスのピーク。制御された無効化により、メモリの連続性が維持され、ヒット率は 厩舎.

断片化を的を絞って解消する:リセット戦略

wasted_memoryが著しく上昇し、ヒット率が低下した場合は、私は リセット opcache_reset() を使用して、負荷の低い時間帯に実行します。その直後に、重要なルートのウォームアップを行い、キャッシュを素早く埋めて負荷のピークを回避します。あるいは、PHP-FPM や Apache を再起動して、共有メモリセグメントを完全に更新することもあります。 リセットのたびに、キャッシュが計画通りに回復しているかを確認するため、ヒット率、wasted_memory、free_memoryを監視します。夜間の定期的な再起動は、頻繁に フラグメンテーション 構築する。.

予防策:適切なデプロイとウォームアップ

私はリリースを新しいディレクトリにデプロイし、シンボリックリンクを使って フィックス /var/www/html/current のようなパスを変更し、OPcache がパスの変更に伴う古いデータを蓄積しないようにします。切り替え直後に、制御されたリセットを実行します。 人気のあるページ、RESTルート、ショップのビューをリクエストするスクリプトを使用することで、キャッシュを的を絞って温めます。これにより、ヒット率は急速に高い水準まで上昇し、ユーザーはメンテナンス期間をほとんど感じることなく済みます。この徹底した対応により、 フラグメンテーション パーマネントだ。

WordPress、WooCommerce、フレームワークの実践的なヒント

プラグインの数が少ないWordPressブログでは、memory_consumptionを128~256 MB、max_accelerated_filesを少なくとも8000に設定し、さらにrevalidate_freqを60~120秒に設定すると、多くの場合、パフォーマンスが向上します。 大規模なWooCommerceショップでは、メモリ256~512 MB、max_accelerated_filesを20000以上、そしてinterned_strings_bufferを16~32 MBに設定すると、より安定して動作します。 Laravel や Symfony などのフレームワークでは、ベンダーの規模にもよりますが、多くの場合、20000~40000 のファイルインデックスと、256~512 MB 以上のメモリが必要です。よくあるトラブルを回避したい方は、以下の簡潔なヘルプをご参照ください。 OPcacheの設定ミス WordPressのセットアップにおいて。以下の表は、有用な 標準値 一緒にね。

プロジェクトの種類 メモリ消費 max_accelerated_files 再評価 interned_strings_buffer
WordPress入門 128~256 MB 8,000~10,000 60~120秒 8~16 MB
WooCommerce/Medium 256~384 MB 20.000+ 60~180秒 16~32 MB
大規模ショップ/マルチサイト 384~512 MB以上 30.000+ 120~300秒 32~48 MB
Laravel/Symfony 256~512 MB以上 20.000–40.000 60~180秒 16~32 MB

上級編:副作用のないプリロードとJIT

PHP 7.4 以降では、opcache.preload を使用することで、起動時に頻繁に使用されるクラスや関数をプリロードできます。これにより、コールドスタート時のレイテンシが低減され、ヒット率が安定します。 なお、プリロードはPHPプロセスのライフサイクルに強く依存している点に留意が必要です。プリロードされたファイルに変更があった場合、opcache_reset()を実行するだけでは変更が適切に反映されないため、PHP-FPMやApacheを意図的に再起動する必要があります。 また、PHP 8.x では JIT についても検討する価値があります。opcache.jit_buffer_size パラメータは、JIT コンパイル用に独立したメモリを予約します。JIT は OPcache のメトリクスに直接影響を与えませんが、CPU 負荷や応答時間を改善する可能性があります。 JITを有効にしている場合は、共有メモリセグメントに余分な負荷がかからないよう、ウォームアップとメモリの余裕を特に慎重にテストしています。.

アロケーターの詳細を理解する:free 対 wasted

OPcacheは共有メモリをチャンク単位で管理します。スクリプトを削除または置換する際、隙間が生じますが、そのサイズは新しいバイトコードブロックのサイズと正確に一致しないことがよくあります。これらの隙間は 無駄メモリー. free_memory それに対して、一貫性があり、実用的に活用できるメモリがあります。無駄なメモリ(wasted)の割合が高い一方で、一見「空き容量が多い」ように見えるのは、実際の容量を隠してしまう典型的なパターンです。 デプロイ後にwasted_memoryがどれほど急速に増加するかを観察しています。わずか数分でその割合が急増する場合は、パスの不安定さ、再検証間隔が短すぎる、あるいはコードの変更頻度が高い(例えば、頻繁に再生成されるテンプレートファイルなど)ことを示す兆候だと解釈しています。 Huge Code Pagesは管理上のオーバーヘッドを軽減し、それによって断片化の傾向を多少抑えることはできますが、適切なデプロイ戦略の代わりにはなりません。.

体系的なサイズ決定:正しい寸法決めの手順

単に「感覚的に」増やすのではなく、計画的に進めています:

  • 完全なウォームアップと日中の負荷がかかった後の、used_memory のピーク値を測定しています。.
  • 安定した状態(リセット後、デプロイ前)におけるwasted_memoryの平均値を合計します。.
  • リリース、季節的な負荷、および成長を見込んで、%のヘッドルームを20~30分確保する予定です。.

これらの要素から、opcache.memory_consumption の目標値が導き出されます。 opcache.max_accelerated_filesについては、すべてのPHPファイル(ベンダーファイルを含む)をカウントし、アップデートによる変動を吸収するために、実際のファイル数より30~50 %分多く制限値を設定します。 調整後、num_cached_scripts が継続的に制限値を大幅に下回っているか、またウォームアップ後にヒット率が 99 % 以上で安定しているかを確認します。.

ウォームアップ・プレイブック:迅速かつ的確に動作温度まで到達

ウォームアップを行うことで、コールドスタート時のピークを防止し、バイトコードをより均等に分散させることができます。私は2段階のウォームアップを行っています:

  1. 技術的なウォームアップ:主要なルート(ホーム、ログイン、カート、チェックアウト、検索API)を並行してトリガーします。.
  2. コンテンツのウォームアップ:ログやアナリティクスから、アクセス数の多いページやRESTエンドポイントを読み込みます。.

コンパクトなウォームアップスクリプト(シェル)の例:

#!/usr/bin/env bash
set -euo pipefail
BASE="https://example.org"
URLS=(
  "/" "/wp-login.php" "/shop/" "/cart/" "/checkout/"
  "/wp-json/wp/v2/posts?per_page=1" "/wp-json/wc/store/products?per_page=1"
)
for u in "${URLS[@]}"; do
  curl -fsS -m 10 -H "User-Agent: Warmup" "$BASE$u" &
done
wait

より深い統合を行うために、頻繁にアクセスされるファイルに対して opcache_compile_file() を呼び出す PHP エンドポイントを追加で利用することも可能です。重要:ウォームアップスクリプトは、リセットの直後、トラフィックを開放する前のリリースパイプラインに組み込む必要があります。.

デプロイ方式:ブルー/グリーン、ローリング、シンボリックリンク

シンボリックリンクのパスを固定したBlue/Greenデプロイメントでは、パスの変動を回避できます。複数のアプリケーションサーバーにまたがるローリング戦略では、手順を厳密に同期させます。まず新しいコードを同期させ、次に各ホストでリセットとウォームアップを行い、最後にトラフィックを切り替えます。 PHP-FPM では、リロードと再起動を区別しています。リロードは設定を再読み込みしますが、既存の共有メモリセグメントは多くの場合そのまま実行され続けます。一方、 リスタート このセグメントを再生成し、断片化を確実に解消します。Apache上でPHPをモジュールとして実行している環境では、クリーンな再起動を行うことで同じ効果を得られます。各環境ごとに、どのコマンドが「実際に」OPcacheをクリアするのかを明確に記録しておき、夜間のメンテナンス時間を計画通りに確保できるようにしています。.

特殊なケース:マルチテナント、CLI、およびワーカー

マルチテナント環境では、テナント間でコードが共有されないよう、個別のFPMプールを使用し、opcache.validate_permission=1に設定しています。これにより、セキュリティが向上し、予期せぬキャッシュの競合が減少します。 CLIジョブについては、opcache.enable_cliを確認しています。デフォルトでは無効になっており、これはWebパス内の断片化には影響しません。しかし、長時間実行されるCLIワーカーを運用している場合は、CLI-OPcacheを有効にすると有益です。その場合、リセットやウォームアップについても同様のルールが適用されます。 動的に生成される、あるいは頻繁に変更されるPHPファイル(例:ビルド成果物、テンプレート出力など)については、opcache.blacklist_filenameを使用してブラックリストに登録し、チャーン(頻繁な更新)およびそれに伴うフラグメンテーションを回避しています。.

ファイルおよびパスの検証を微調整する

opcache.revalidate_path を使用することで、include_path やシンボリックリンクのパスが変更された際に、OPcache がパスを再解決するかどうかを指定します。 安定した本番環境では、この値を通常0に設定しています。シンボリックリンクを介してリリース間を切り替える際は、アプリケーションがそれに依存しているかどうかを確認し、必要に応じて revalidate_path を個別に有効にします。 file_update_protection は、ファイル変更直後の過度な再コンパイルを防ぐためのものです(数秒間の短い保護期間)。ファイルをアトミックに更新するビルドパイプラインでは、新しくデプロイされたコードが速やかにキャッシュに反映されるよう、この値を適度に設定しています。 opcache.file_cache(ディスク上のセカンドレベルキャッシュ)は、再起動後のウォームアップを早めるためにオプションとして有用です。共有メモリ内の断片化の代替にはなりませんが、コールドスタートのコストを低減し、それによって慌ただしいコンパイルの頻度を減らすことができます。.

よくある誤解とアンチパターン

  • „「メモリを増やせばすべて解決」:規律なくキャッシュを過剰に増やすと、後々断片化を招くだけだ。まずはデプロイとリセットの戦略を明確にすべきである。.
  • „「Reloadだけで十分」:多くの環境では、共有メモリセグメントはそのまま残ります。完全なリセットを行うには、再起動、あるいは opcache_reset() + ウォームアップを行う予定です。.
  • „「%のヒット率98%なら問題ない」:負荷がかかっている状況では、1~2の%が増えると、コンパイル回数が増え、顕著なレイテンシのピークが生じます。目標は、ウォームアップ後の%ヒット率を99%以上に保つことです。.
  • „「私たちは常に無効化を行っている――それがより安全だからだ」:頻繁な無効化は断片化を加速させる。より良い方法は、リリース時点での管理された無効化である。.

トラブルシューティング:体系的な手順

  1. ステータスの取得:opcache_get_status()、used/free/wasted_memory、num_cached_scripts、opcache_hit_rate を保存する。.
  2. 制限値を確認する:wasted_memory >= 15 % または free_memory <= 10 % であるか?その場合は、対策を計画する。.
  3. 制限値の確認:max_accelerated_files 対 実際のファイル数、interned_strings_buffer 対 文字列の使用量。.
  4. 「リセット+ウォームアップ」のテスト:落ち着いた状況で実行し、実行前後の指標を比較する。.
  5. デプロイパターンのカスタマイズ:固定パス、シンボリックリンクの切り替え、リリース時のみの無効化。.
  6. モニタリングを強化する:数日・数週間にわたる傾向を観察し、デプロイ後のピークとの相関関係を分析する。.

モニタリング用のシンプルなステータスエンドポイントは、実際の運用において非常に役立っています:

<?php
header('Content-Type: application/json');
echo json_encode(opcache_get_status(false));

日常生活で役立つ要約

私は、wasted_memoryを5 %未満に、ヒット率を99 %以上に、free_memoryを10 %の閾値から遠ざけています。なぜなら、こうした数値は明確な 信号 提供します。値が危険域に達した場合は、直ちにウォームアップを伴うリセットを計画するか、メモリやファイルインデックスを適切に拡張します。安定したパスへのデプロイと制御された無効化により、過去のデータがキャッシュを詰まらせるのを防ぎます。 継続的なモニタリングにより、単なるスナップショットでは把握できないパターンが明らかになります。このアプローチにより、 パフォーマンス 均一に動作し、OPcacheはリスク要因ではなく、信頼できる高速化ツールとして機能します。.

現在の記事

断片化分析のための、PHP Opcache メモリを可視化したサーバー
管理

PHP Opcacheの断片化を検知・解消し、パフォーマンスを最大化

PHP OPcacheの断片化を検知し、監視と設定によってこれを解消し、的確なPHPチューニングによってアプリケーションのパフォーマンスを最適化する方法について学びましょう。焦点:プロフェッショナルなホスティング環境におけるPHP OPcacheの断片化。.

LFUおよびLRUエヴィクションポリシーを視覚化するための、サーバーとデータストリームを用いたRedisキャッシュの可視化
データベース

RedisのLFUとLRU:どちらのエヴィクションポリシーが適切か?

キャッシュを最適に設定するには、RedisのLFUおよびLRUによるエヴィクションの仕組みを理解しておく必要があります。この記事では、これらを直接比較し、ポリシーの選択に役立つ情報を提供します。.