バッファリングとは
Perlの出力関数であるprint関数は、バッファリングを行います。バッファリングとは「データを貯めておく」という意味です。Perlのprint関数は実際に呼び出されても、即座にファイルに内容を書き出しません。書き込み内容をバッファリングしておいて、バッファがある容量をこえると実際にファイルに書き出します。
バッファリングを無効にしたいという場合は、以下の記事をご覧ください。
以下はバッファリングを実感するサンプルです。すぐにはファイルに書き込まれないことがわかると思います。
use strict; use warnings; # 書き込み用のファイル( 上書きするので注意 ) my $file = "sample20080811.txt"; open(my $fh, ">", $file) or die "Cannot open $file: $!"; print $fh "遅延書き込み\n"; # print関数呼び出し print "ファイルサイズはまだ" . -s $file . "バイトで書き込まれていません。\n"; sleep 3; # closeと同時にバッファをファイルに書き出す(遅延書き込み)。 close $fh or die "Cannot close $file"; print "この時点で書き込まれました。サイズは" . -s $file . "バイトです。\n"; sleep 3;
Perlのprint関数のバッファリングの仕様
(1)ブロックバッファリング
Perlのprint関数は標準でブロックバッファリングを行います。(例外はディスプレイに出力する場合で、行バッファリングを行います。Perl 5.6以降 )
ブロックバッファリングとは、一定のバイト数までバッファにデータを蓄積するバッファリング方式のことです。バッファに蓄積された書き込み内容が一定のバイト数をこえると、実際にファイルに書き込みが行われれます。
一定のバイト数というのは、設定によりますが一般的に4kBくらいだと思います。また、ファイルがクローズするタイミングでも、バッファの内容がファイルに書き出されます。
(2)行バッファリング
ディスプレイに出力するときは、行バッファリングが行われます。改行文字がでてくるまで、バッファに書き込み内容が蓄積され、改行が出現したときに、バッファの内容がファイルに書き出されます。
バッファリングと遅延書き込み
print関数が、書き込み内容をバッファに貯めて一度に出力するのは、ファイルへの出力のコストが非常に高いからです。ファイルに書き込むということはディスクにアクセスするということです。
ディスクI/Oというのは、メモリI/Oに比べて非常に速度が遅いので、ディスクアクセスへの回数をできるだけ減らすことがプログラムの性能向上につながります。
こういう理由で、Perlはprint関数を呼び出したときに実際に書き込みを行わず、書き込みバッファに一定バイトまでデータを蓄積して一度にファイルに書き出します。これを遅延書き込みと呼びます。
コード解説
(1)ブロックバッファリングが行われる
print $fh "遅延書き込み\n"; # print関数呼び出し print "ファイルサイズはまだ" . -s $file . "バイトで書き込まれていません。\n"; sleep 3;
print 関数で$fhに書き込みましたが、この時点ではまだ内容が書き出されず、ファイルのサイズは0バイトのままです。書き込み内容が、バッファに蓄積されている状態です。
ちなみに、ディスプレイへの出力は、行バッファリングですので、"\n"が出現した時点で出力されます。
(2)遅延書き込みが行われる
# closeと同時にバッファをファイルに書き出す(遅延書き込み)。 close $fh or die "Cannot close $file"; print "この時点で書き込まれました。サイズは" . -s $file . "バイトです。\n"; sleep 3;
$fh をクローズした時点で、バッファにある書き込み内容がファイルに出力されます。遅延書き込みが行われたことがわかると思います。