私の PHP アプリケーションでは、多くのファイル(主にログ)の最後から複数行を読み取る必要があります。最後の1つだけが必要な場合もあれば、数十または数百が必要な場合もあります。tail
基本的に、Unixコマンドと同じくらい柔軟なものが必要です。
ここには、ファイルから最後の 1 行を取得する方法に関する質問があり (ただし、N行が必要です)、さまざまな解決策が示されています。どちらが優れていて、どちらが優れているかはわかりません。
私の PHP アプリケーションでは、多くのファイル(主にログ)の最後から複数行を読み取る必要があります。最後の1つだけが必要な場合もあれば、数十または数百が必要な場合もあります。tail
基本的に、Unixコマンドと同じくらい柔軟なものが必要です。
ここには、ファイルから最後の 1 行を取得する方法に関する質問があり (ただし、N行が必要です)、さまざまな解決策が示されています。どちらが優れていて、どちらが優れているかはわかりません。
インターネットで検索すると、さまざまな解決策が見つかりました。それらを次の 3 つのアプローチにグループ化できます。
file()
PHP 関数を使用する単純なもの。tail
システム上でコマンドを実行する不正行為。fseek()
_私は最終的に 5つの解決策を選択 (または作成) しました。
tail
の可能な解決策ですが、少し大きな問題があります: がtail
利用できない場合、つまり非 Unix (Windows) またはシステム機能を許可しない制限された環境では実行されません。すべてのソリューションが機能します。任意のファイルから期待される結果を返すという意味で、任意の行数を要求します (解決策 #1 を除き、大きなファイルの場合に PHP のメモリ制限を破ることができ、何も返されません)。しかし、どちらが良いですか?
質問に答えるために、テストを実行します。それがこれらのことが行われる方法ですよね?
ディレクトリにあるさまざまなファイルを結合する100 KBのサンプル ファイルを用意しました/var/log
。次に、5 つのソリューションのそれぞれを使用して、ファイルの末尾から1、2、..、10、20、... 100、200、...、1000行を取得する PHP スクリプトを作成しました。1 つのテストはそれぞれ 10 回繰り返され ( 5 × 28 × 10 = 1400テストのようなものです)、平均経過時間をマイクロ秒単位で測定します。
PHP コマンド ライン インタープリターを使用して、ローカルの開発マシン (Xubuntu 12.04、PHP 5.3.10、2.70 GHz デュアル コア CPU、2 GB RAM) でスクリプトを実行します。結果は次のとおりです。
解決策 #1 と #2 は悪いもののようです。解決策 3 は、数行を読む必要がある場合にのみ有効です。ソリューション #4 と #5 が最適なようです。 動的バッファー サイズがアルゴリズムを最適化する方法に注意してください。バッファーが削減されるため、数行の実行時間は少し短くなります。
もっと大きなファイルで試してみましょう。10 MBのログ ファイルを読み取る必要がある場合はどうなるでしょうか。
解決策 #1 は、はるかに悪いものです。実際、10 MB のファイル全体をメモリにロードすることは、良い考えではありません。1MB と 100MB のファイルでもテストを実行しましたが、実質的に同じ状況です。
小さなログファイルの場合は?これは、 10 KBファイルのグラフです。
解決策 #1 が今のところ最適です。10 KB をメモリにロードすることは、PHP にとって大したことではありません。また、#4 と #5 のパフォーマンスも良好です。ただし、これはエッジ ケースです。10 KB のログは、150/200 行のようなものを意味します...
すべてのテスト ファイル、ソース、および結果を ここからダウンロードできます。
解決策 5は、一般的なユース ケースに強く推奨されます。すべてのファイル サイズでうまく機能し、数行を読み取るときに特に優れたパフォーマンスを発揮します。
10 KB を超えるファイルを読み取る必要がある場合は、解決策 1を避けてください。
解決策#2 と#3 は、私が実行する各テストに最適なものではありません: #2 は 2 ミリ秒未満で実行されることはありません。 )。