LWN: 使用buffered I/O但是不用担心page cache被占满了!

本文探讨Linux中BufferedI/O与DirectI/O的优缺点,提出通过新增RWF_UNCACHED标志结合两者优点的方法,避免大数据量访问时页缓存资源耗尽的问题,提升系统性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关注了就能看到更多这么棒的文章哦~

Buffered I/O without page-cache thrashing

By Jonathan Corbet
December 12, 2019

原文来自:https://lwn.net/Articles/806980/

ps. 建议读一下原文下面Axboe跟其他读者的讨论。

Linux提供了两种file I/O模式:buffered模式和direct模式。Buffered I/O会经过kernel的page cache,更加易用,针对那些会访问多次的数据来说能显著提高访问性能;Direct I/O则是把user-space的数据和存储设备之间进行直接搬运,在某些情况下操作系统的缓存(caching)并不需要的话,这种方式能更加快一些,不过用起来比较复杂,对于不注意的开发者来说容易碰到陷阱。现在,Jen Axboe提出了一个方案,可能可以得到direct I/O的大多数好处,而不会容易陷入那些陷阱。

Direct I/O比起buffered I/O的性能优势有几方面。首先它能完全避免把data在user space和page cache之间进行复制引入的消耗。这个消耗可能已经很大了,不过多数情况下这还不是最大的问题。最大的问题是对buffered I/O在page cache上的影响。

当一个进程需要访问一个或多个大文件进行访问的时候,这种大数据量的buffered I/O访问会很快就把page cache都完全用光,也就是说大量memory也会都被这些文件数据缓存都占用掉了。如果这个进程在这些I/O操作之后不再访问这些数据了,那么其实完全没有必要把这些数据保存在memory中。在kernel在做别的事情想要分配memory的时候,kernel就需要先回收(reclaim)一些内存page,这种操作对整个系统的性能都有影响,哪怕只是回收那些用作此次I/O缓存的page也会对系统性能有影响。

内存管理子系统在这种情况下会尽量采用比较优化的方式来处理,首先把buffered I/O导致进入cache的page都串到inactive list上去,如果短期内没有再次访问这些page的话,这些page就会被优先回收掉。不过,哪怕就是按照这种方式实现之后,还是会有不少额外损耗的。Axboe做了个简单的测试,得到如下结果:“测试用例很简单,就是对一个size是RAM size的10倍大小的数据集进行随机读操作。起初性能还不错,接下来page cache填满之后,性能就大跳水了。IO线程的CPU占用率直线上升,kswapd会占用一个CPU核心的100%的时间来努力满足内存需求。”

采用direct I/O可以避免这种问题,不过这样也会印发一些direct I/O特有的问题和挑战。Axboe的结论是,可以采用第三条路,能集合前两种方式的优点。

这个第三种方式就是针对preadv2()和pwritev2()系统调用增加一个新的flag,RWF_UNCACHED。使用这个flag的时候,根据受影响的文件page是否在page cache里面,而对发起的I/O操作进行两方面的改变。如果数据在page cache内,这个I/O操作正常进行,就当RWF_UNCACHED flag不存在一样,数据读写访问会直接使用page cache里的内容。如果这个page不在page cache内,就会先加到page cache中去,不过仅仅针对这一次I/O操作而已,当操作结束时就会把这些page从page cache中移除。

换句话说,这种情况下buffered I/O不会改变page cache的状态,本来在page cache里的内容仍会继续留在page cache内,但是不会新增内容到page cache中。这样进行的I/O操作可以得到buffered I/O的大多数好处,包括方便易用、可以快速访问cache(已经缓存)的数据,却不会让那些不需要进入cache的数据耗用memory资源。按Axboe的说法,结果很显著:“使用这种方式进行测试,读写访问可以一直很平稳,不会迫使kernel的kswapd挥汗如雨地努力工作。其实kswapd都没有出现过。”

这个新增的flag看起来可以对很多workload带来显著改善。特别是对那些已知只需要使用一次的数据,或者当应用程序会在user space自己维护缓存(caching)的情况下,都会很喜欢RWF_UNCACHED flag。

这个新方案的实现并不复杂,整个patch set 海包括了对io_uring的支持,总共也只牵涉到200行代码而已。当然,正如Dave Chinner指出,这里还缺少一些改动:所有的测试基础架构(testing infrastructure)都需要确保RWF_UNCACHED的行为要严格按预期进行,不能损坏数据。Chinner也指出了在write实现里面的一些性能问题,建议整个I/O操作应该一起进行flush,而不是用Axboe实现的逐个page进行flush的。Axboe已经贴出了修改后的patch,至于完成test case以及完善文档描述的工作会在后面进行。

如果RWF_UNCACHED能在真实的workload中也证明自己的价值,那么很多人可能都会觉得自己多年以前就该想到这种方法。这个世界就是这样的,解决问题并不难,难的地方在于先搞清楚要解决的是具体什么问题,当然,还有包括写test case和文档。。。

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值