提问人:1f604 提问时间:6/22/2023 最后编辑:1f604 更新时间:7/1/2023 访问量:249
为什么O_DIRECT比正常读取慢?
Why O_DIRECT is slower than normal read?
问:
这是我正在使用的代码:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
int main (int argc, char* argv[]) {
int fd;
int alignment = 4096;
int bufsize = 4096 * 4096;
char* buf = (char*) memalign(alignment, bufsize);
int i, n, result=0;
const char* fname = "1GB.txt";
if ((fd = open(fname, O_RDONLY|O_DIRECT)) < 0) {
printf("%s: cannot open %s\n", fname);
exit(2);
}
while ( (n = read(fd,buf,bufsize)) > 0 )
for (i=0; i<n; ++i)
result += buf[i];
printf("Result: %d\n", result);
return 0;
}
这是我正在运行的命令:
echo 1 > /proc/sys/vm/drop_caches
time ./a.out 1GB.txt
如果没有O_DIRECT,刷新页面缓存后只需 1.1 秒,使用 O_DIRECT 则需要 2.5 秒。
我尝试更改对齐方式和 bufsize。增加 bufsize 以将运行时间减少到 1.79 秒。增加 bufsize 以将运行时间缩短至 1.75 秒。将对齐减少到 512 将运行时间减少到 1.72 秒。我不知道还能尝试什么。4096 * 4096 * 4
4096 * 4096 * 64
我不明白为什么使用 O_DIRECT 会使代码变慢。可能是因为我使用的是磁盘加密吗?
我在 Debian 12 内核 6.1.0-9-amd64 上
答:
我认为 Linus 在这个旧的邮件列表线程中总结得很好,有人遇到了与你相同的问题:O_DIRECT
2002 年 5 月 10 日星期五,林肯·戴尔写道:
因此,O_DIRECT 2.4.18 中仍然显示为 55% 的性能命中率,而不是 No O_DIRECT。有人有什么线索吗?
是的。
O_DIRECT没有提前阅读。
要O_DIRECT获胜,您需要使其异步。
一直让我感到不安的是O_DIRECT 界面很愚蠢,很可能是一只疯狂的猴子设计的 关于一些严重的精神控制物质[*]。
它根本不漂亮,而且性能也不是很好 因为接口不好(读/写的同步性是其中的一部分 但是,固有的页表行走是另一个问题)。
我敢打赌,你可以通过拆分 实际的 IO 生成和“用户空间映射”是理智的。
因此,您遇到的读取操作速度较慢,因为没有执行预读或缓存,这是没有 的正常行为。O_DIRECT
除非你想请求读取更大的大小,否则如果你进行分块读取,你只有在实现异步操作(例如使用 io_uring
)时才能真正受益。Linus 还在上面链接的邮件列表线程中提出了其他有趣的解决方案。O_DIRECT
评论
pwrite()
read()
O_DIRECT
评论
O_DIRECT
bufsize
read
mmap()
O_DIRECT
mmap()
mmap
O_DIRECT