Mat*_*nte 2 c unix linux optimization posix
我正在实现一个高效的文本文件加载器,并在这篇文章中从 GNU grep 的作者那里找到了一些很好的建议:http : //lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html
他建议的一件事是将页面对齐的数据块调用 read() 到页面对齐的缓冲区中。显然,这允许内核避免一些额外的缓冲。
我一直在寻找,但没有听到其他人支持这一说法。将 read() 调用到页面对齐的缓冲区(可能使用 mmap/posix_memalign 等分配)实际上更有效吗?如果它不是真的,它是否曾经是真的?它是否严重依赖于底层文件系统或其他类似因素?
谢谢!
通常,read()会读入内核缓冲区,然后将其复制到用户空间。这个额外的副本是正在讨论的内容。
Linux 通过 O_DIRECT 标志支持“直接 I/O”到open(). 这将跳过内核缓冲并直接读入用户空间缓冲区。但是,这种直接 I/O 需要对齐的访问和缓冲区。所以我不认为那篇文章的作者意味着当你对齐时会发生奇迹,而是如果你仔细对齐,你可以使用“更接近金属”的技术来提取更多的性能。
mmap()是获得相同效果的更简单的方法。首次设置映射时,不会发生 I/O。当用户第一次访问映射中的页面时,会触发页面错误,内核通过分配用户页面并执行 I/O 来填充它来处理页面错误。没有副本。但同样,I/O 发生在页面大小的块中,在页面对齐的边界上。
这是否是一个大问题取决于内存复制相对于 I/O 的速度有多快,以及 CPU 时间的多少比例用于复制而不是做实际工作。例如,Web 服务器通常甚至不必查看它正在读取的内容:它只是将它再次写出一个套接字(这会产生另一个副本)。这就是为什么大量工作进入了“零复制”技术,如系统调用sendfile()和splice(). 这些是专门的工作负载。通常,缓冲太小而不必担心。