是什么原因导致内核在page_fault上占用CPU?

问题描述

硬件/操作系统:Linux 4.9,64G RAM。

16个守护程序正在运行。每次读取随机的简短(100字节)的5GiB文件,将其作为守护程序启动时通过mmap()映射的内存进行访问。每个守护程序读取自己的文件,因此总共16个5GiB文件。

每个守护程序每秒可能读取10次。不会太多,磁盘负载很小。

有时(5分钟内有1个事件,没有周期,完全是随机的),一些随机的守护程序被followind堆栈(参见图片)卡在内核代码中300毫秒。这与严重故障并没有关联:严重故障以大约每秒100 ... 200的恒定速率运行。磁盘读取也是恒定的。

是什么原因造成的?

stack got with perf record

图片文字:__list_del_entry isolate_lru_pages.isra.48 shrink_inactive_list shrink_node_memcg shrink_node node_reclaim get_page_from_freelist enqueue_task_fair sched_clock __alloc_pages_nodemask alloc_pages_vma handle_mm_fault __do_page_fault page_fault

解决方法

您的堆栈中有shrink_node和node_reclaim函数。它们被称为释放内存(free命令行工具显示为buff / cache):https://www.kernel.org/doc/html/latest/admin-guide/mm/concepts.html#reclaim

释放可回收物理内存页面并对其进行重新利用的过程称为(惊奇!)回收。 Linux可以异步或同步回收页面,具体取决于系统状态。当不加载系统时,大多数内存都是空闲的,分配请求将立即从空闲页面供应中得到满足。随着负载的增加,空闲页面的数量会减少,当空闲页面达到某个阈值(高水位标记)时,分配请求将唤醒kswapd守护程序。它将异步扫描内存页面,或者如果其中包含的数据在其他位置可用,则释放它们,或者将其驱逐到后备存储设备(还记得那些脏页吗?)。随着内存使用量的增加甚至更多,并达到另一个阈值(最小水印),分配将触发直接回收。在这种情况下,分配将停止,直到回收足够的内存页面以满足请求为止。

因此,您的64 GB RAM系统会出现剩余可用内存不足的情况。此内存量足以容纳每个5 GB的12个文件的副本,并且守护程序使用16个文件。与使用Readahead技术("Linux readahead: less tricks for more",ols 2007 pp273-284man 2 readahead)的应用程序所需的数据相比,Linux可能从文件读取的数据更多。 MADV_SEQUENTIAL也可以打开此机制,https://man7.org/linux/man-pages/man2/madvise.2.html

   MADV_SEQUENTIAL

按顺序期望页面引用。 (因此,在 给定的范围可以提前大胆地阅读,并且可能是 访问后不久将其释放。)

  MADV_RANDOM

以随机顺序预期页面引用。 (因此,请提前阅读 可能没有通常的有用。)

不确定守护程序如何打开和读取文件,是否为MADV_SEQUENTIAL激活了它们(或者glibc或任何其他库添加了此标志)。 THP也可能会产生一些影响-透明大页面https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html。正常的4.9内核是从2016年开始的,计划在2019年https://lwn.net/Articles/789159/进行文件系统的扩展,但是如果您使用RHEL / CentOS,则某些功能可能会反向移植到4.9内核的分支中。

您应该定期检查freecat /proc/meminfo的输出,以检查守护程序和Linux内核预读如何使用内存。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...