ファイルの行数を計測するスクリプトのベンチマーク
't'を1000個ならべたものを1行として
1行のファイル、101行のファイル,201行のファイル、、、1001行のファイルを作成する
for(my $n=1;$n<= 1001;$n+= 100){ open my $t,">","text/$n.txt"; $a=0; while($a++ < $n){ print $t 't'x1000; print $t "\n"; } close $t; }
ファイルができたか確認する。
$ for i in text/*; do wc -l $i; done | sort -k1 1 text/1.txt 101 text/101.txt 201 text/201.txt 301 text/301.txt 401 text/401.txt 501 text/501.txt 601 text/601.txt 701 text/701.txt 801 text/801.txt 901 text/901.txt 1001 text/1001.txt
- oneln: 1行づつ読み込んで変数をインクリメント
- hensu: 1行づつ読み込んで$.変数へのアクセスで行数を取得
- pipe: open関数でパイプを開き、wcコマンドの出力をcutコマンドで切りとって取得
- sysop: sysreadを使って、trで改行の数を計測
use Benchmark qw(cmpthese); my $cnt; my $line; my $repeat = 100; my $func = { oneln=>sub{ my $file = shift; sub{ $cnt = 0; open my $fh,"<:utf8",$file or die $!; $cnt++ while(<$fh>); close $fh; } }, hensu=>sub{ my $file = shift; sub{ $cnt = 0; open my $fh,"<",$file or die $!; 1 for(<$fh>); $cnt = $.;# close 前に変数に入れとく close $fh; } }, pipe=>sub{ my $file = shift; sub{ $cnt = 0; open my $p,"echo `wc -l $file` | cut -d ' ' -f1 |" or die $!; $cnt = <$p>; chomp $cnt; close $p; } }, sysop=>sub{ my $file = shift; sub{ $cnt = 0; open(FILE, $file) or die $!; while (sysread FILE, $buffer, 4096) { $cnt += ($buffer =~ tr/\n//); } close FILE; } } }; for(my $r=1;$r<=1001;$r+=100){ printf "==%03d===================================\n",$r; cmpthese( 100=>{map {$_=>$func->{$_}("text/$r.txt")} keys %$func} ); }
このベンチマークスクリプト、どうやら、Linuxで実行したときとOSXで実行したときで
結果が違う。
Linuxの場合は、100行以上のファイルを読み込む場合には、openでwcコマンドを呼びだすpipeが爆速。
OSXの場合は、全ての場合で1行読み込んでインクリメントするonelnが高速。
ファイルシステムやキャッシュ機構の特性が関係しているのかもしれない。
P.S.
OSXの場合、cut の引数で -d ' 'を指定した場合、空白の連続も1つ1つに分割されてしまう為、このままでは正常に数値の取得ができない。
以下のようにすると取得できる。
open my $p,"echo `wc -l $file`| cut -d ' ' -f1"