2

我正在实现一个高效的文本文件加载器,并在这篇文章中从 GNU grep 的作者那里找到了一些很好的建议:http: //lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html

他建议的一件事是将页面对齐的数据块读取()调用到页面对齐的缓冲区中。显然这允许内核避免一些额外的缓冲。

我一直在寻找,我还没有听到其他人支持这一说法。将 read() 调用到页面对齐的缓冲区(可能使用 mmap/posix_memalign 等分配)实际上更有效吗?如果它不是真的,那它曾经是真的吗?它是否在很大程度上取决于底层文件系统或其他类似因素?

谢谢!

4

1 回答 1

5

通常,read()会读入内核缓冲区,然后将其复制到用户空间。这个额外的副本是正在讨论的内容。

Linux 通过 O_DIRECT 标志支持“直接 I/O”到open(). 这将跳过内核缓冲并直接读入用户空间缓冲区。但是,这种直接 I/O 需要对齐的访问和缓冲区。所以我不认为那篇文章的作者意味着当你对齐时会发生魔法,而是如果你仔细对齐,你可以使用“更接近金属”的技术来提取更多的性能。

mmap()是获得相同效果的一种更简单的方法。首次设置映射时,不会发生 I/O。当用户第一次访问映射中的页面时,会触发页面错误,内核通过分配用户页面并执行 I/O 来填充它来处理该页面错误。没有副本。但同样,I/O 发生在页面大小的块中,在页面对齐的边界上。

这是否重要取决于内存复制相对于 I/O 的速度,以及 CPU 时间用于复制而不是实际工作的比例。例如,Web 服务器通常甚至不必查看它正在读取的内容:它只需将其从套接字中再次写入(这会产生另一个副本)。这就是为什么大量工作已经进入“零拷贝”技术,如系统调用sendfile()splice(). 这些是专门的工作负载。通常,缓冲太小而无需担心。

于 2013-09-26T15:05:53.457 回答