动机
空闲页跟踪功能允许跟踪哪些内存页 工作负载访问的空闲状态。此信息对 估计工作负载的工作集大小,而工作集的大小又可以用于 配置工作负载参数、设置内存控制组限制、 或者决定在计算群集中将工作负载放置到何处。
通过CONFIG_IDLE_PAGE_TRACKING=y来启用。
用户接口
空闲页面跟踪API位于/sys/kernel/mm/page_idle。目前, 它由唯一的读写文件/sys/kernel/mm/page_idle/bitmap组成。
该文件实现了位图,其中每个位对应一个内存页。位图由8字节整数数组表示,PFN #i处的页面映射到数组元素#i/64的bit #i%64,字节顺序为本机。当某个bit位被置位时,对应的页面处于空闲状态。
如果页面被标记为空闲后未被访问,则认为该页面处于空闲状态(有关“已访问”的更多详细信息,请参阅IMPLEMENTATION DETAILS部分)。要标记页面空闲,必须通过写入文件。写入文件的值与当前位图值或。
仅跟踪对用户内存页的访问。这些页映射到进程地址空间、页缓存和缓冲页、交换缓存页。对于其他页面类型(例如。SLAB pages)将页面标记为空闲的尝试被静默忽略,因此此类页面永远不会被报告为空闲。
对于大页,空闲标志只在头页上设置,因此必须读取/proc/kpageflags才能正确计数空闲的大页。
如果未在8字节边界上启动读/写,或者读/写的大小不是8字节的倍数,则对/sys/kernel/mm/page_idle/bitmap进行读/写操作将返回-EINVAL。写入此文件超过max PFN将返回-ENXIO。
也就是说,为了估计工作量未使用的页面数量,应该:
1.通过设置/sys/kernel/mm/page_idle/bitmap中对应位,将工作负载的所有页面标记为空闲。如果工作负载由进程表示,则可以通过读取/proc/pid/pagemap来查找页面,或者如果工作负载被放置在内存控制组中,则通过使用/proc/kpagecgroup过滤外来页来查找页面。
2.等待工作负载访问其工作集。
3、读取/sys/kernel/mm/page_idle/bitmap,统计设置位数。如果想要忽略某些类型的页面,例如,由于不可回收的锁定页面,他或她可以使用/proc/kpageflags过滤掉它们。
有关/proc/pid/pagemap、/proc/kpageflags和/proc/kpagecgroup的详细信息,请参见Documentation/vm/pagemap.txt。
实施详情
内核在内部跟踪对用户内存页的访问,以便在内存不足的情况下首先回收未引用的页。如果最近通过进程地址空间访问过一个页面,则认为该页面被引用,在这种情况下,它被映射到的一个或多个PTE将设置访问位。或标记由内核显式访问(参见mark_page_accessed())。后者发生于以下情况:
-用户空间进程使用系统调用读取或写入页面(例如。读(2)或写(2))
-用于存储文件系统缓冲区的页被读取或写入,因为进程需要文件系统元数据存储在其中(例如。目录树如所示)
-一个页面由设备驱动程序使用get_user_pages()访问 当脏页由于内存回收或超过脏内存限制而写入交换或磁盘时,它不会被标记为引用。
空闲内存跟踪功能添加了一个新的页标志,即空闲标志。此标志通过写入/sys/kernel/mm/page_idle/bitmap (请参见USER API部分)手动设置,并且每当引用上面定义的页时,该标志将自动清除。
当页面被标记为空闲时,必须清除它映射到的所有PTE中的“已访问”位,否则我们将无法检测来自进程地址空间的对页面的访问。为了避免与回收器(如上所述,回收器使用Accessed位来提升主动引用的页面)的干扰,引入了另一个页面标志,即Young标志。当由于设置或更新页面的空闲标志而清除PTE Accessed位时,将在页面上设置Young标志。回收程序将Young标志视为额外的PTE Accessed位,因此将认为这样的页面被引用。
由于空闲内存跟踪功能基于内存回收程序逻辑,因此它只对LRU列表中的页起作用,其他页将被静默忽略。这意味着,如果用户内存页被隔离,它将忽略它,但是由于通常不会有很多,所以它不会明显影响整个结果。为了不中断空闲页位图的扫描,也可以跳过锁定页。
1
2
https://github.com/sjp38/idle_page_tracking/blob/master/pageidle.c
https://github.com/luochenglcs/wss/blob/master/wss-v2.c