Perlの出力バッファリング

Perlでprint関数を実行してもすぐに画面に表示されない・・・
仕様です。print、即出力を想定してると痛い目みます。


Perlでは出力されるべき文字列はまずはメモリにバッファリングされ、決められた条件を満たした時にまとめて出力されます。
その基本的な考え方はこうです。

ディスプレイへの出力は行バッファリング
改行がきたら出力
その他のハンドルへの出力はブロックバッファリング
一定サイズたまったら出力
オートフラッシュを有効化するとコマンドバッファリング
print(、printf、write)が実行されるたびに出力

あと出力ハンドルがcloseされたとき、プログラムの終了時はもちろん出力はフラッシュされます。



じゃ見てみましょう。

ディスプレイへの出力は行バッファリング

#! /usr/bin/perl

sleep 1;
print "111";
sleep 1;
print "222\n";
sleep 1;
print "333";
sleep 1;

1秒後

$ perl line_buf.pl

2秒後

$ perl line_buf.pl
111222

3秒後

$ perl line_buf.pl
111222

4秒後

$ perl line_buf.pl
111222
333$

というわけで改行出力時にまとめて出力されてることがわかります。


その他のハンドルへの出力はブロックバッファリング

ファイル出力で確認します。

#!/usr/bin/perl

open my $fh, ">>", "test.log";

for(1..9){
  sleep 1;
  print "$_\n";
  print $fh $_ x 1023 . "\n";
}

1秒後

$ tail -f test.log

2秒後

$ tail -f test.log

3秒後

$ tail -f test.log

4秒後

$ tail -f test.log
111<略>111
222<略>222
333<略>333
444<略>444

...

というわけで一定サイズ(テスト環境では4kバイト)たまったらまとめて出力されてます。


オートフラッシュを有効化するとコマンドバッファリング

上記のようなバッファリングを抑止したいときはオートフラッシュを有効化します。
そうするとprint、printf、writeを実行するごとにバッファがフラッシュされる、つまりprint、即出力が実現できます。


どうやるかは・・・長くなったので別の日記で!!