syncとfsync

理解が曖昧だったので、きちんと調べてみた。

sync(2)

sync() を呼び出すと、バッファされたファイルのメタデータとデータ本体に対して行われた全ての変更が、対応するファイルシステムに書き込まれる。

fsync(2)

fsync() は、ファイル記述子 fd で参照されるファイルの、メモリ内で存在する修正されたデータ (つまり修正されたバッファキャッシュページ) を、ディスクデバイス(またはその他の永続ストレージデバイス) に転送 (「フラッシュ」) し、これにより、システムがクラッシュしたり、再起動された後も、変更された全ての情報が取り出せるようになる。「フラッシュ」には、ライトスルー (write through) や (存在する場合には) ディスクキャッシュのフラッシュも含まれる。この呼び出しは 転送が終わったとデバイスが報告するまでブロックする。

さらに調べてみると、カーネルスレッドのpdflushがバッファからディスクに書き込みをする、らしい。 これだけでは面白くないのでwriteのたびにfsyncして、同期的にファイル書き込みしたときの速度差を測ってみる。

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char** argv)
{
    int fd;
    char buff[1024];
    int i;

    sprintf(buff, "test%d\r\n", getpid());

    fd = open("/tmp/kotaro", (O_WRONLY | O_CREAT));
    for (i = 0; i < 10000; i++) {
        write(fd, buff, strlen(buff));
        if ( argc > 1 ) {
            fsync(fd);
        }
    }
    close(fd);
}

fsyncなし

$ time ./write_fsync

real    0m0.026s
user    0m0.004s
sys     0m0.018s

fsyncあり

$ time ./write_fsync --with-fsync

real    0m2.771s
user    0m0.017s
sys     0m0.336s

1ループあたり0.27msもfsyncありのほうが遅いという結果に。

さらに素晴らしい記事を発見。勉強になるなぁ。 http://d.hatena.ne.jp/naoya/20070523/1179938637