ホームページ >バックエンド開発 >PHPチュートリアル >PHP で大きなファイルをロードする場合の require と file_get_contents のパフォーマンスの比較

PHP で大きなファイルをロードする場合の require と file_get_contents のパフォーマンスの比較

WBOY
WBOYオリジナル
2016-06-23 13:46:011161ブラウズ

開発プロセス中に、require を使用して大規模 (数百 K、場合によっては数メガバイト) の構成ファイルをロードすると、応答タイムアウトが発生することがわかりました。この構成ファイルの内容をシリアル化し、file_get_contents を使用してファイルを取得し、それを逆シリアル化してロードすると、はるかに高速になります。

約 2 週間の調査を経て、その理由がおおよそわかりました。

まずはPHPの処理から始めましょう。 PHPには実は起動処理とリクエストに応答する処理の2つがあります。 Apache のモジュールとして、PHP は Apache に 2 つの関数を登録しています。1 つは Apache の起動時に実行される関数です: sapi_startup; もう 1 つは Apache がリクエストを受信したときに呼び出す関数です: php_handler

起動プロセス:

Apache の起動

- -> sapi_startup

- -> php_module_startup (PHP 起動マスター スイッチ)

- -> zend_startup (グローバル変数の初期化、コンパイルおよび実行関数の初期化を含む)リクエストプロセス:

Apache がリクエストを受信します

-> sapi_startup

- -> zend_activate (初期化コンパイラ、初期化エグゼキュータ、起動スキャナを含む)

- -> )

;-& Gt; Zend_execute (各 OPCODE を実行します)

-& gt; Zend_deactive (このリクエストで使用されたデータを消去します)

Require または Include などの関数が見つかった場合は、ZEND_EXECUTE ステージから ZEND_compiler ステージに戻ります。 、PHP の説明を開始し、PHP のプロセスを実行します

zend_compiler と zend_execute ステージを除いて、require と file_get_contents のオーバーヘッドは基本的に同じです

そして、apc 拡張機能がサーバーにインストールされます。ステージはどちらも同じと考えられます

次に、パフォーマンスの違いは zend_execute ステージにあります

まず、vld 拡張子を使用して、2 つのファイルによって生成されたオペコードの数を確認してみましょう。
結果は、生成されたオペコードの数が 20,000 を超えていることを示していますが、そのほとんどはデータを構築するためのものですが、file_get_contents は 6 つのオペコードのみを生成します。これら 2 つの関数の実行は 2 つの部分に分けることができます: ファイルを取得し、構成ファイルに配列を構築します

最初にファイルの読み取りについて説明します。必要な読み取りメカニズムは、バッファーを使用してファイルをメモリに読み取ることです。 8192 バイトのループ。一方、file_get_contents は mmap を使用してファイルを仮想メモリに直接マッピングします。この場合、require には file_get_contents よりも多くのシステム コールが必要になります。 File_get_contents は、ユーザー モードとカーネル モードの間でそれほど多くの切り替えを行う必要はありません。このステップでは、file_get_contents が勝ちます。

構築配列をもう一度見てみましょう。require 構築のメカニズムは、file_get_contents が受信テキストを解析する unserialize 関数を使用する間に、20,000 を超えるオペコードを生成することです。その後、レベルごとに配列が構築されます。配列を構築するという考え方は同じですが、require の各追加データのオーバーヘッドは unserialize のオーバーヘッドよりも大きくなります。このラウンドでは file_get_contents の方がわずかに優れています

ただし、file_get_contents は PHP 内の関数呼び出しです。そして、 require は組み込みの opcode であるため、 file_get_contents を呼び出すときのオーバーヘッドは、 require よりわずかに大きくなります

そのため、ファイルが小さい場合、 file_get_contents がファイルを読み取るときのメモリ マッピングの利点を活かすことができません。ファイルが大きい場合、require には 2K2K が必要となるため、2 つは部分的に等しくなります。read システム コールをループするとパフォーマンスが低下します。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。