mmap() vs. reading blocks (翻译)

原文地址:
mmap() vs. reading blocks

mmap vs read

在我试图为linux上的mmap/read的性能找到一个确切的答案的过程中, 我在linux内核邮件列表中发现了一篇精彩的文章(链接). 这已经是2000年的文章, 显然至今linux已经在内核区的IO和虚拟内存方面有了许多改进, 但是这篇文章依旧很好地解释了mmap和read的性能问题.

相比于read调用, 一次mmap调用的系统开销更大(正如epoll的开销要比poll更大). 在进程间改变虚拟内存的映射更是一个代价很大的操作, 因为进程间的切换本身就会消耗很大CPU资源. 但是你使用read读取一个文件, 因此read/write属于系统IO,都在内核区有磁盘缓存, 只要使用系统IO都会优先检查内核区的缓存.

但是通常来说, 提前使用mmap完成内存映射要比调用read时在磁盘做随机访问要快得多,特别是当你访问的对象在磁盘上分布地很分散.

内存映射允许你把页面保存在缓存当中,直到你完成对页面的操作. 也就是说, 你经过一段长时间地读写一个文件,然后关闭文件,再重新打开, 页面依然在缓存当中. 当你使用read调用时, 你的文件页面会在缓存当中老化,进而被系统清洗出缓存. 当然,如果你只是读写一个文件,然后马上丢弃它,没有耗时长的操作的话,你是感受不到缓存页面的老化的.
(如果你想通过mlock给内存页面加锁来防止页面被换出缓存,那相当于你想要比精心设计过的磁盘缓存机制表现得更聪明, 通常来说,这种蠢事几乎不可能提高系统性能.)

直接读取一个文件既简单又高效.

对于mmap/read的讨论让我想起了另外两个有关性能的讨论:
1) 通常来说,非阻塞IO其实比阻塞IO慢, 这使很多java程序员震惊. 但你只要知道了非阻塞IO需要更多的系统调用, 这就很好理解.
2) 通常来说, epoll其实比poll慢, 这使很多网络编程程序员震惊. 但你只要知道了管理epoll显然需要更多的系统调用,这就很好理解.

结论:

使用mmap内存映射的情况:
1) 随机访问数据;
2) 文件页面会在内存中保留很长一段时间;
3) 多个进程间会共享该文件页面.(如果不是为了共享页面,MAP_SHARED可不是多友好的.)

使用read的情况:
1) 顺序访问数据;
2) 使用一次之后就可以丢弃, 数据不需要常驻内存.

只要mmap或read能让你的程序结构更加简单, 那就是对的,并没有那么多标准答案. 现实中也确实没有非常确切的方法能表明哪一个是更高效的, 因为不同的应用场景有不同测试案例和对照标准.

Answered Jun 17 ‘11 at 8:33

Dietrich Epp

翻译:2018年6月12日
杨梓涛

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值