【发布时间】:2021-04-25 22:43:24
【问题描述】:
我想知道两者的区别
char *text = (char *)malloc(4096);
memset(text, 'a', 4096);
int fd = open(filepath, O_RDWR | O_CREAT | O_DIRECT);
for(int i=0; i<1000; i++) {
write(fd, (void *)text, 4096);
fsync(fd);
}
close (fd);
和
char *text = (char *)malloc(4096);
memset(text, 'a', 4096);
int fd = open(filepath, O_RDWR | O_CREAT | O_DIRECT | O_SYNC); //<----Difference
for(int i=0; i<1000; i++) {
write(fd, (void *)text, 4096);
// fsync(fd); <--------------------------------------------------Difference
}
close (fd);
上面代码的性能比下面的要慢。
【问题讨论】:
-
可能没有区别 - 由于您不检查返回值,因此两者都未检测到失败;-)。
-
在更严重的方面,根据 open(2) 手册页,在使用 O_SYNC 标志打开的文件上,写入应该可以工作“就像每次 write(2) 之后都调用 fsync (2)",就是你做的,所以两者应该是等价的。不知道为什么会有差异。智能驱动程序是否仍然可以组合连续的 write()(但如果有中间的 fsync() 则不能)?这在我的书中会违反 O_SYNC 语义保证。
-
我发现另一件值得注意的事情是文件系统/驱动程序似乎确实也刷新了磁盘缓存。 sync(2) 手册页警告说,由于写入延迟和磁盘缓存,当调用返回时,数据实际上可能尚未在磁盘上。这显然与 fsync() 不同。
-
循环后的 fsync 可能会大大增加吞吐量,但是,正如已经评论的那样,写入后的 fsync 基本上是 O_SYNC 所做的(不考虑内核的智慧)
-
感谢您的回答!我的两个 SSD(三星 860 evo 和 980 pro)都出现了巨大的性能差异。我正在考虑通过
hdparm -W0 /dev/860evoSATA SSD 来禁用磁盘缓存,但这里还有一个问题:如何禁用 NVMe SSD 的磁盘缓存?