3

巨大なログ ファイル (約 5 ~ 1000 万行) があります。すべての行をトラバースして処理を行う必要があります。私は巨大なランタイムを見ています。

perl以下に示すように、ファイルを読み取る2つの方法を認識しています。

(1)異なる方法のパフォーマンスを比較するにはどうすればよいですか? ベンチマークメカニズムはありますか?

(2)最も効率的な方法とその理由は? 利用可能な3番目のより良い方法はありますか?

1 つのオプションは、両方のメソッドを実装してランタイムをチェックすることです。しかし、ここでは、何が高速または低速で実行されるのかを理解しようとしています。この点で私を助けていただければ幸いです。

方法 1

open FOPEN, '<', $file or die $!;
my @lines = <FOPEN>;
chomp @lines;
foreach (@lines) {
    # do something on $_
}

方法 2

open FOPEN, '<', $file or die $!;
while (<FOPEN>) {
    chomp;
    # do something on $_
}
4

3 に答える 3

8

方法 2 は間違いなく行く方法です。方法 1 は、ファイル全体をメモリ (変数 @lines 内) にコピーします。ログ ファイルが 1 GB を超える場合は、プログラムがクラッシュすることが予想されます。方法 2 は、ファイルを 1 行ずつ反復処理し、ほぼ一定のメモリ使用量を維持します。

お役に立てれば。

編集:(ベンチマークの部分について話すのを忘れていました)

Benchmarkのようなモジュールを使用して、複数の反復で両方の方法のパフォーマンスを比較できます。非常に便利なツールです。非常に大きなファイルの場合、方法 2 が方法 1 よりもかなりの差でパフォーマンスが向上することがわかります。

于 2013-09-28T12:19:28.953 に答える
8

ファイルの行を順不同で処理する必要がない限り、ファイル全体を配列に吸収することはメモリを浪費するだけなので、必ずループで読み取る必要があります。whilePerl IO システムは、ファイルの読み取りをバッファリングし、要求に応じてバッファからデータの各行を渡すことで、これを可能な限り効率的にします。

また、おそらくchomp各行も必要ありません。文字列の末尾にある予備の改行は問題にならない可能性があります。

ファイルで何をしたいかによっては、関心のある情報だけを含む小さなファイル (または複数のファイル) への入力を前処理することが適切な場合があります。

常に字句ファイルハンドルを使用します。つまり、

open my $fh, '<', $file or die $!;
while (<$fh>) {
    # do something on $_
}

これは効率とは関係ありません。それは単に良い習慣です。

于 2013-09-28T12:27:12.443 に答える
1

ファイル サイズが大きく、ファイル全体を読み取っている場合は、IO をブロックしないで sysread を実行することを検討してください 。 perl sysread ノンブロッキング"

于 2013-09-28T18:57:37.033 に答える