LWN:使用cachestat()来检查page-cache状态!

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

Checking page-cache status with cachestat()

By Jonathan Corbet
December 6, 2022
DeepL assisted translation
https://lwn.net/Articles/917096/

内核中的 page cache 会将文件的 page 保存在 RAM 中,让这些 page 可以不需要每次都要浪费从持久性存储设备上读取的时间就可以直接访问到。应用程序通常完全不知道 page cache 的相关行为;它加快了速度,这是最重要的一点。不过,有些应用程序可以从了解某个文件某一时刻有多少在 page cache 中,从而得到一些改善。Nhat Pham 提出的 cachestat() 系统调用就是一系列尝试中的最新成果,从而可以将这些信息提供出来。

事实上,即使是目前现有的内核代码,也有可能了解到一个文件中哪些 page 是在于 page cache 中了。应用程序只需要用 mmap()将某个文件 map 到它的地址空间内,然后调用 mincore() 就可以返回一个 vector,其中展示了该文件中有哪些 page 是驻留的。但这是一个开销很大的解决方案;它需要建立一个(可能本来根本不需要的)mapping,并且返回的信息对于许多应用程序的需求来说粒度太细了。

新建议的 cachestat() 系统调用则比较简单:

struct cachestat {
    __u64 nr_cache;
    __u64 nr_dirty;
    __u64 nr_writeback;
    __u64 nr_evicted;
    __u64 nr_recently_evicted;
};

int cachestat(unsigned int fd, off_t offset, size_t len, size_t cstat_size, 
  struct cachestat *cstat);

这个调用将检查 fd 所代表的 file 中的哪些 page,会从指定的 offset 开始,一直到达到 len 字节的位置,并计算处于不同驻留状态的 page 数量。offset 必须是与 page 对齐的;如果有必要的话,len 会被四舍五入为 page size 的整数倍。然后,在返回出来的 cstat 所指向的结构中可以看到这些 count 数量。在该结构中,nr_cache 代表了指定范围内存在于 page cache 中的 page 数量,nr_dirty 是这些 page 中 dirty 页面的数量(也就是已经被修改并且尚未写回到持久性存储设备中的),nr_writeback 是目前正在进行 write back 的 page 数量。

nr_evicted 字段提供了曾经驻留在 cache 中但后来被强制从 cache 中移除的 page 数量,而 nr_recently_evicted 是那些在近期被强制移除的 page 数量。在这种场景下的 "recent past" 是指自从相关 page 被强制移除后被 evict 的 page 数量;如果这个数字小于进程的 working-set(工作集)size,则这个 evict 就被判定为是最近发生的。这些 count 数值是通过查看大约十年前加入内核的 shadow page-table 的信息而获取的。

cachestat 结构的 size 必须作为 cstat_size 提供给 cachestat()。这样设计的接口就可以在将来在该结构中加入新的字段了;如果 cstat_size 小于内核中已知的 size,数据将只会根据提供出来的 size 来给出,从而保持兼容性。(如果 cstat_size 大于内核所期望的 size,这根调用会返回 EINVAL 错误从而失败)。

由于不需要对要查询的文件进行 mapping 和 unmapping,cachestat() 避免了大部分由 mincore() 方式所产生的开销。这个调用中返回的是简单的计数,而不是详细的、逐个 page 的信息,这也会有所帮助。似乎想要这种信息的应用程序都是对对驻留在 cache 中的 page 数量感兴趣,而并不关心哪些 page 当前是在驻留的。所以返回更详细的数据就没有意义了。

不过还有一个问题在这个 patch set 中没有得到很好的回答,那就是:什么样的应用程序会从这些信息中受益?当 LWN 在 2010 年报道类似的工作时(当时的系统调用被称为 fincore()),涉及到的使用场景是及调用 posix_fadvise()的应用程序,在访问数据之前将其引入到 page cache 中。这些应用程序(SQLite 显然是其中之一)知道后续的数据访问行为模式,但他们对他们的数据在某个特定时间内有多少可以进入 page cache 这个信息不太了解。通过调用 cachestat(),这样的应用程序可以了解到在它要使用这些 page 的时候,它正希望进行 prefetch 的 page 是否还存在于 cache 中。如果这些 page 被 evict 掉了,那么 prefetch 就会使 page cache 负载过重,从而引发更多的工作;在这种情况下,应用程序就可以退而求其次从而获得更好的性能。

所以 cachestat() 似乎是有用的,但是内核中是否还愿意接受这个新的系统调用,目前还有待观察。十多年来,增加这种功能的尝试一直没能成功,也许是由于这种使用场景经常是高度专业化的环境下。但是,也许有那么一些可能,这次的新接口以及新的推动力量可以让这个功能在这次能得到认可。

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

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

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

format,png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值