2016-08-17 27 views
1

私は処理が必要な非常に長い行のファイルを持っていますが、バッファが十分に大きくないか、非常に処理が遅いために長い行には時間がかかることがあります。コードサンプルは次のとおりです。<>オペレータのバッファサイズ

open FH, "<$fname" or die "..."; 
while (<FH>) { 
    my @arr = split //, $_; 
    pop @arr; 
    pop @arr; 
    ... for some "limited small portion of the string length" number of times ... 
    pop @arr; 
    if ($arr[-1] eq '0') { 
     print "done!\n"; 
     last; 
    } 
    push @big_arr, join('', @arr); 
} 

行処理は「重い」ではありません。

私はそれを解決するために何かを探してPerlIO::buffersizeを見つけましたが、それはしばらくの間維持されなかったように見えます。バージョン0.001のモジュールを使用したくありません。 <>オペレータのバッファサイズを変更するにはどうすればよいですか?あるいは、それを読む前に行の長さを知る方法がありますか?<>? - ファイルから読み込むバイト数のため、数値に設定することができます

$/

+0

私たちはここでどのくらい話していますか?私はレコードの区切り文字でこの構造体を使用しましたが、かなりの数の行が長くて、特に問題ないと思います。あなたがあなたを減速させる 'while'ループだと確信していますか? – Sobrique

+0

@Sobrique私は確信していませんが、このコードをはるかに短い行のファイルで実行したとき、それは魔法のように働き、とても速く走っていました。線は非常に長いです。あたかも大きなテキストファイルをすべて1行または2行に収めているかのように考えてください(私はこれらのファイルの形式を制御しません)。 – yonyon100

+0

しかし、あなたは '$ /' - レコードセパレータを設定できます。あなたがラインを上に分けることができる適切なものはありますか? – Sobrique

答えて

3

それはあなたが必要とすると、このである可能性があります。

$ /を整数への参照、整数を含むスカラー、または整数に変換可能なスカラーは、行の代わりにレコードを読み込みます。最大レコードサイズは、参照される整数の文字数です。

出典:perlvar

+2

これはPerlの内部バッファーサイズを変更しませんが、とにかく問題になることはほとんどありません。 – Borodin

+1

OPはまだデータを行として読み込みたいので、CからPerlに組み立てる行を動かすと、実際には少し遅くなります。 – ikegami

3

変更Perlのリードバッファサイズは、あなたのプログラムの速度に重大な違いを作ることはほとんどありません、あなたが見ている影響は長く読みの結果であるとはるかに可能性がありますディスクドライブ自体からの時間。上Perl Read-Ahead I/O Bufferingを見てみましょうperlmonks.org

さらに、readを使用するか、または固定サイズにレコードセパレータ$/を設定することで、独自のバッファリングを実装し、あなたはまだに持っているとして、あなたのプログラムを遅くする可能性が高い以上のものですあなたが読んだものをデータの行に分けるが、Perlのコードでそれをやらなければならない。

$/を固定レコードサイズに変更する尺度は、依然としてPerlの標準、おそらく8KBのバッファ。唯一の違いは、あなたに戻って渡されるデータの量ではなく、区切り文字列

1

どのように私は<>オペレータのバッファサイズを変更することができるの位置のバイト数に応じて決定されること?ですか

<>は、任意のサイズに成長することができ、スカラに読み込むので、私はあなたがreadシステムコールに渡されたバッファのサイズを参照していると思います。

5.14より前には、4つのKiBチャンクのファイルハンドルからPerlを読み込みました。 5.14ではこの設定が可能で、デフォルトは8 KiBでした。

$ perl -e'print("x" x 9_999, "\n") for 1..2' >large_lines 

$ strace 5.10.1t/bin/perl -e'my $line = <>' large_lines 2>&1 | grep read.*xxx 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 

$ strace 5.14.2t/bin/perl -e'my $line = <>' large_lines 2>&1 | grep read.*xxx 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 
perlが構築される場合にのみこれは read含むすべての緩衝読み出し機能、に適用される次のコマンドを

./Configure -Accflags=-DPERLIOBUF_DEFAULT_BUFSIZ=8192 

を使用して、構成することができる

readline(れる<>は別名である)、readpipeeofですが、sysreadではありません。


注番号への参照に$/を設定するreadline<>)が依然としてバッファされるread、として機能させるようにします。

$ strace perl -e'$/ = \8193; my $block = <>' large_lines 2>&1 | grep read.*xxx 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 

あなたが実際に単一readシステムコールを実行する場合は、sysreadを使用する必要があります。

$ strace perl -e'sysread(STDIN, $buf, 8193)' <large_lines 2>&1 | grep read.*xxx 
read(0, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8193) = 8193 
関連する問題