Linux マシンで fsync のパフォーマンスをテストしているときに、fsync はファイルにデータを挿入するとファイルのサイズが大きくなり、非常に時間がかかることがわかりました。
環境: 12 コアの 2-CPU Linux バージョン 2.6.32_1-14-0-0 (scmpf@pwd) (gcc バージョン 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC) ) #1 SMP 月 3 月 31 日10:42:09 CST 2014 ext2 ファイルシステム
テストコード:
static int _openfile_w(char *file, bool is_sync)
{
int flag = O_CREAT|O_RDWR;
if (is_sync)
{
flag |= O_SYNC;
}
return open(file,flag,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
}
int test_fsync(void)
{
#define NUMOFFSYNC 1000
int fd = 0;
char * filename = "/home/zhangguangzhou/tmp/0";
fd = _openfile_w(filenames, false);
if (fd <= 0)
{
UB_LOG_WARNING("%s open index file %s error",__FUNCTION__, filename);
return -1;
}
char data[1024];
memset((void*)data, 'c', sizeof(data));
for( int i = 0; i < NUMOFFSYNC; i++)
{
if (lseek(fd, i*sizeof(data), SEEK_SET) < 0)
{
UB_LOG_WARNING("%s lseek index error, transid:curidx:%d",
__FUNCTION__, i);
return -1;
}
if (write(fd, data, sizeof(data)) != sizeof(data))
{
UB_LOG_WARNING("%s write index error, transid:curidx:%d",
__FUNCTION__, i);
return -1;
}
if (fsync(fd) < 0)
{
UB_LOG_WARNING("%s fsync error, cur_datano:%d",
__FUNCTION__, i);
return -1;
}
}
return 0;
}
結果:
上記の test_fsync プログラムを "echo "" >/home/zhangguangzhou/tmp/0" の後に実行すると、各 fsync は平均で 8 ミリ秒かかります。しかし、繰り返し実行すると、平均で 50 ミリ秒かかります。2回目以降の実行で。ファイルの途中から insertint データをテストしたり、異なるサイズのデータで挿入したりしましたが、結果はほとんど変わりませんでした。
質問: 書き込みによってファイルが大きくなる場合、fsync の余分な時間がかかるのは何ですか?
fysnc の inode IO について考えてみましたが、どちらもファイル変更時の inode メタデータを更新する必要があるため、ファイル増加書き込みとファイル増加なし書き込みの両方で inode IO は同じです。