ディスクキャッシュを凌駕: misc/buffer2006年02月09日 14時50分08秒

もう何年も好んで使い続けてきたプログラムの中に buffer と言うものがあります。要は、cat。一つだけ違うのは、バッファリングのサイズが桁違いに大きいだけです。FreeBSD はもちろん、OpenBSD、Linux、NetBSD でも使っていました。*BSD では ports になっているのですが、linux ではなかったので一時はパッケージにしてみたりもしたものです。

buffer は起動されると、共有メモリを割り当てて、fork() します。その後、親は入力を読み続け、読み込んだものを共有メモリに書き込みます。子プロセスは共有メモリを読み出し、出力に書き出します。

ここまで、言えば分かったでしょうか。IO 系のプロセスとCPU 系のプロセスをパイプで結ぶことによって、CPU の利用率をあげることが出来るのです。例えば

 tar cvf - Mail | bzip2 > file.tar.bz2
等とやった場合、細かいファイルが大量にあるので tar が IO 中に bzip2 は止まり、bzip2 が圧縮中に tar が止まります。bzip2 は 8 MB のブロックで圧縮するので、tar で止まってしまうのです。最近にシステムは昔に比べたらディスクキャッシュがよくなったからと言ったところで、8 MB も先読みをすることはありません。っていうか、常にそんなに大量に先読みしていたら、ただ無駄でしかありません。Linux では、ディスクキャッシュがあるので「そんなのいらないよ。」と言われたりしたものですが。とにかく、buffer を挟むことによって、tar は bzip2 の圧縮中にファイルを読み、bzip2 は続けて圧縮し続けられるのです。rsh などでも有効です。

まあ、問題としては実装の悪さでしょうか。実装上の問題で、最大メモリが 20 MB です。加えて、メモリのアドレスの保持の仕方にも問題があり、OpenBSD で共有メモリのアドレスが共有されるプロセス間でも変わるように、カーネルが書き換えられたときに buffer も動かなくなって、patch を送ったものです。20 MB 以上のメモリを扱えるように変更するのも、大変なので buffer を連結して凌いだり。

次回