Linuxの遅延書込みをどうにかしたい
Linuxで書き込み速度の遅いフラッシュメモリに大きいファイルを書き込もうとすると、最初のうちはものすごい高速で書き込まれ、途中から遅くなったりひどい場合ずっと止まったようになってしまう。ファイルサイズまで達した時に止まったままになることもある。(実際には待っていれば完了する。)でも、書き込みの速いメディア上だとそういうことは起こらない(ように見える)。なんだこれは。
おそらく非同期で書き込んでいるのではないか、ということで検証プログラム。
#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(const int argc, char* const argv[]) { // O_SYNCの有無で比較しよう const int fd = open(argv[1], O_WRONLY | O_TRUNC | O_SYNC); fprintf(stderr, "fd: %d\n", fd); const int sizebuf = 1024*1024; char* const buf = (char*)malloc(sizebuf); int i; for(i=0; i<1024; ++i) { fprintf(stderr, "%d\n", i); write(fd, buf, sizebuf); } free(buf); close(fd); }
O_SYNCが無しだと前述のような状況になり、O_SYNCが有りだと同期書込するので待たされることはない。(ただし、遅い。)
つまり遅延書き込みを行なっているせいのようだ。たしかに遅延書き込みはパフォーマンスを上げるのでありがたいのだが、プログレスバーが止まっているように見えるのはいただけない。MacやWindowsではこんなことはおこらない。
いまのところ最善の策は見つけていないのだが、カーネルパラメータを調整して遅延書き込みの閾値を下げると若干改善した。
例えば
sudo /sbin/sysctl -w vm/dirty_bytes=16777216
とかどうでしょう。小さすぎるとパフォーマンスが悪くなるので、連続アクセスが一番速い媒体の速度ぐらいにあわせておくのがいいのだろうか。
dirty_bytesって何?って場合は、このページが参考になる。
できればバッファサイズに上限を設定できたらいいなと思うんだけど、見当たらない。
こういうソフトウェア的な仕組みはまだまだ不勉強なことが多いなぁ。