(jp) =
プリロードがどのように機能するかについて書いた後、実際にその影響を測定する時が来ました。 結果に飛び込む前に、全員が同じページにいることを確認する必要があります。つまり、何を測定していて、何を測定していないかです。
プリロードが自分のプロジェクトに実際に影響を与えるかどうかを知りたいので、趣味のプロジェクトaggregate.stitcher.ioのホームページで、実際のプロジェクトでベンチマークを実行します。
このプロジェクトは Laravel プロジェクトであり、明らかにいくつかのデータベース呼び出し、ビューのレンダリングなどを行います。これらのベンチマークは Laravel プロジェクトのパフォーマンスについて何も伝えていないことを明確にしたいと思います。 それだけ プリロードが提供できる相対的なパフォーマンスの向上を測定します。
繰り返しますが、これらの結果から誰も間違った結論を導き出さないようにするためです。私のベンチマークは それだけ プリロードを使用しない場合と比較して、パフォーマンスに相対的な影響があるかどうかを測定します。 これらのベンチマークは、パフォーマンスがどれだけ向上するかについては何も述べていません。 これは、サーバーの負荷、実行中のコード、現在のページなど、いくつかの変数に依存します。
舞台を整えましょう。

# セットアップのプリロード
プリロードを使用するかどうかによってどれだけ正確に得られるかを測定したくないので、Apache Bench を使用してローカル マシンでこれらのベンチマークを実行することにしました。 一度に 50 の同時リクエストで、5000 のリクエストを送信します。 Web サーバーは、php-fpm を使用する nginx です。 プリロードの初期のバージョンにはいくつかのバグがあったため、ベンチマークを正常に実行できるのは PHP 7.4.2 の早い段階です。
プリロードを無効にしたシナリオ、すべての Laravel とアプリケーション コードをプリロードしたシナリオ、プリロードされたクラスの最適化されたリストを使用したシナリオの 3 つのシナリオのベンチマークを行います。 後者の理由は、プリロードにはメモリのオーバーヘッドも伴うためです。「ホット」なクラス (非常に頻繁に使用されるクラス) のみをプリロードする場合、パフォーマンスの向上とメモリ使用量の間のスイート スポットを見つけることができる可能性があります。
# プリロード無効
php-fpm を起動し、ベンチマークを実行します。
./php-7_4_2/sbin/php-fpm --nodaemonize
ab -n 5000 -c 50 -l http:
これらは結果でした: 私たちは処理することができます 64.79 1 秒あたりのリクエスト数、平均時間は 771ms リクエストごと。 これが私たちのベースライン シナリオです。次の結果をこのシナリオと比較できます。
# 素朴なプリロード
次に、すべての Laravel とアプリケーション コードをプリロードします。 リクエストですべての Laravel クラスを使用することはないため、これは単純なアプローチです。 厳密に必要なファイルよりも多くのファイルをプリロードしているため、ペナルティを支払う必要があります。 この場合、1165 個のクラスとその依存関係がプリロードされ、合計 1366 個の関数と 1256 個のクラスがプリロードされます。
前に述べたように、その情報は次の場所から読み取ることができます。 opcache_get_status:
opcache_get_status()['preload_statistics'];
取得する別の指標 opcache_get_status プリロードされたスクリプトに使用されるメモリです。 この場合、17.43 MB です。 実際に必要とするよりも多くのコードをプリロードしていますが、単純なプリロードはすでにパフォーマンスにプラスの影響を与えています。
| リクエスト/秒 | リクエストあたりの時間 | |
| プリロードなし | 64.79 | 771ms |
| 単純なプリロード | 79.69 | 627ミリ秒 |
すでにパフォーマンスの向上が見られます。1 秒あたりにより多くのリクエストを処理できるようになり、1 つのリクエストを処理する平均時間が ±20% 減少しました。
# 最適化
最後に、最適化されたプリロード リストを使用した場合のパフォーマンスの向上を比較します。 テスト目的で、プリロードを有効にせずにサーバーを起動し、そのリクエスト内で使用されるすべてのクラスをダンプしました。
get_declared_classes();
次に、合計 427 のこれらのクラスのみをプリロードしました。 すべての依存関係を合わせると、643 個のクラスと 1034 個の関数がプリロードされ、約 11.76 MB のメモリが占有されます。
このセットアップのベンチマーク結果は次のとおりです。
| リクエスト/秒 | リクエストあたりの時間 | |
| プリロードなし | 64.79 | 771ms |
| 単純なプリロード | 79.69 | 627ミリ秒 |
| 最適化されたプリロード | 86.12 | 580ミリ秒 |
これは、プリロードを使用しない場合に比べてパフォーマンスが約 25% 向上し、単純なアプローチを使用した場合に比べて 8% 向上します。 ただし、特定のページ用に最適化されたプリロード リストを生成したため、この設定には問題があります。 実際には、すべてのページをカバーしたい場合は、おそらくより多くのコードをプリロードする必要があります。
別のアプローチとして、運用サーバーで数時間または数日間にわたってどのクラスが何回ロードされているかを監視し、それらのメトリックに基づいてプリロード リストをコンパイルすることもできます。アプローチ — 本格的なフレームワークに基づいて構築された実際のプロジェクトにも、パフォーマンスにプラスの影響があります。 どれだけ正確に得られるかは、コード、サーバー、および使用しているフレームワークによって異なります。 私はそれを試してみてください!
//platform.twitter.com/widgets.js