当我在我的 Linux 机器上测试 fsync 的性能时,我发现 fsync 将数据插入到文件中会增加文件时会花费大量时间,但在插入仅覆盖现有内容而不增加文件大小的数据时,它的执行速度要快 100 倍。
环境:2-CPU 12 核 Linux 版本 2.6.32_1-14-0-0 (scmpf@pwd) (gcc 版本 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC)) #1 SMP Mon Mar 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;
}
结果:
在 "echo "" >/home/zhangguangzhou/tmp/0" 之后运行上面的 test_fsync 程序,这会清空文件,每个 fsync 平均花费 8ms。但是当重复运行时,平均花费 50 us。在第二次及以后的运行中。当我从文件中间测试插入数据或插入不同大小的数据时,结果几乎没有变化。
问题: 如果写入正在增长文件,那么 fsync 的额外时间是多少?
我想到了fysnc中的inode IO,但是file-growth write和no-file-growth write的inode IO是一样的,因为它们都需要更新文件修改时间的inode元数据。