次のように述べたとき、私の理解は正しいですか。
while(<>) ループ内の条件で $ARGV (つまり、ファイル名) をテストするために CPU サイクルが浪費されています。最初にファイル名をテストしてから、while() ループ内でそれに応じて各行を処理する方が効率的です。このようにして、データ行を取得するたびにファイル名を冗長にチェックすることはありません。
それとも、ダイヤモンド演算子はこれを後者と同じくらい効率的にするために何らかの魔法を行いますか?
次のように述べたとき、私の理解は正しいですか。
while(<>) ループ内の条件で $ARGV (つまり、ファイル名) をテストするために CPU サイクルが浪費されています。最初にファイル名をテストしてから、while() ループ内でそれに応じて各行を処理する方が効率的です。このようにして、データ行を取得するたびにファイル名を冗長にチェックすることはありません。
それとも、ダイヤモンド演算子はこれを後者と同じくらい効率的にするために何らかの魔法を行いますか?
CPUサイクルを無駄にしていますか?
Perlを実行しています。VMで実行されます。グローバル変数の単純なルックアップが意味するポインター逆参照の数を知っていますか? なぜサイクルを気にするのですか?/秒
オペレーターはかなりの量の魔法を暗示してい<>
ますが、これはループを最適化しません。したがって、
my $lastfile = "";
while (<>) {
say "file changed to ", $lastfile = $ARGV if $lastfile ne $ARGV;
print "> $_";
}
チェックはne
すべての行に対して実行されます。コード サイズや開発時間を最適化する場合、これはまったく問題ありません。実行されるオペコードの総数を最適化している場合は、ファイルを明示的に開く方が安価な場合があります。
use autodie;
for my $file (@ARGV) {
open my $fh, "<", $file;
say "file changed to $file";
while (<$fh>) {
print "> $_";
}
}
個人的には、このフォームの方がエレガント (単一割り当てフォーム) だと思いますが、それほど長くはありません。しかし、簡単に言えば、最初の解決策を使用します。なぜなら、まだ長い形式を書いている間に、スクリプトがすでに 1,000 回実行されている可能性があるからです。
概念実証 (以下を参照) として、amon が示した 2 つのスクリプト (それぞれに poc.pl と poc2.pl という名前を付けました) を 10 億行のファイルで実行しました。前者は 21.7% 遅くなりました。結論として、これは膨大な数の行を処理する場合にのみ重要です。その場合、低レベル言語の方が適している場合があります。
bash $ wc -l large.log
1000000000 large.log
bash $ time perl poc.pl large.log >/dev/null
291.16s real 289.89s user 0.73s system
bash $ time perl poc2.pl large.log >/dev/null
239.29s real 238.58s user 0.53s system