Linux上的read()和页面对齐的缓冲区

时间:2013-09-25 02:15:47

标签: c linux unix optimization posix

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

他建议的一件事是对页面对齐的缓冲区执行页面对齐的数据块的read()调用。显然,这允许内核避免一些额外的缓冲。

我一直在寻找,我没有听到其他人支持这种说法。将read()调用到页面对齐的缓冲区(可能用mmap / posix_memalign等分配)是否真的更有效?如果它不是真的,它曾经是真的吗?它是否严重依赖于底层文件系统或其他类似因素?

谢谢!

1 个答案:

答案 0 :(得分:4)

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

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

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

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