![为什么我的 Linux 内核无法回收其 slab 内存?](https://linux22.com/image/711536/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84%20Linux%20%E5%86%85%E6%A0%B8%E6%97%A0%E6%B3%95%E5%9B%9E%E6%94%B6%E5%85%B6%20slab%20%E5%86%85%E5%AD%98%EF%BC%9F.png)
我的系统内存使用量不断增加,直到达到甚至为一些普通事情都要交换的程度,因此变得反应迟钝。罪魁祸首似乎是内核分配的内存,但我很难弄清楚内核到底发生了什么。
我如何知道哪些内核线程/模块/其他内容负责特定块的内核内存使用?
这是系统内存使用情况随时间变化的图表:
该slab_unrecl
值会随着时间推移而增长,与SUnreclaim
中的字段相对应/proc/meminfo
。
当我跑到slabtop
图表末尾并按缓存大小对其进行排序时,它显示了以下内容:
Active / Total Objects (% used) : 15451251 / 15530002 (99.5%)
Active / Total Slabs (% used) : 399651 / 399651 (100.0%)
Active / Total Caches (% used) : 85 / 113 (75.2%)
Active / Total Size (% used) : 2394126.21K / 2416458.60K (99.1%)
Minimum / Average / Maximum Object : 0.01K / 0.16K / 18.62K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
3646503 3646503 100% 0.38K 173643 21 1389144K kmem_cache
3852288 3851906 99% 0.06K 60192 64 240768K kmalloc-64
3646656 3646656 100% 0.06K 56979 64 227916K kmem_cache_node
1441760 1441675 99% 0.12K 45055 32 180220K kmalloc-128
499136 494535 99% 0.25K 15598 32 124784K kmalloc-256
1066842 1066632 99% 0.09K 25401 42 101604K kmalloc-96
101430 101192 99% 0.19K 4830 21 19320K kmalloc-192
19168 17621 91% 1.00K 599 32 19168K kmalloc-1024
8386 7470 89% 2.00K 525 16 16800K kmalloc-2048
15000 9815 65% 1.05K 500 30 16000K ext4_inode_cache
66024 45955 69% 0.19K 3144 21 12576K dentry
369536 369536 100% 0.03K 2887 128 11548K kmalloc-32
18441 16586 89% 0.58K 683 27 10928K inode_cache
44331 42665 96% 0.19K 2111 21 8444K cred_jar
12208 7529 61% 0.57K 436 28 6976K radix_tree_node
627 580 92% 9.12K 209 3 6688K task_struct
6720 6328 94% 0.65K 280 24 4480K proc_inode_cache
36006 36006 100% 0.12K 1059 34 4236K kernfs_node_cache
266752 266752 100% 0.02K 1042 256 4168K kmalloc-16
134640 133960 99% 0.02K 792 170 3168K fsnotify_mark_connector
1568 1461 93% 2.00K 98 16 3136K mm_struct
1245 1165 93% 2.06K 83 15 2656K sighand_cache
结论:
- 内核的 slab 分配器使用了大约 2.3 GB 的 RAM
- 几乎所有这些都是无法回收的
- 其中约 1.3 GB 被
kmem_cache
缓存占用 - 另外 0.5 GB 属于各种大小的 kmalloc 缓存
这是我遇到的难题。我还没搞清楚如何查看这些缓存,并了解它们为何变得如此之大(或为何它们的内存无法回收)。我该如何进一步调查?
答案1
perf kmem record --slab
将捕获分析数据并按 perf kmem stat --slab --caller
内核符号进行小计。
但这并不能解释为什么您的工作负载会这样做。添加perf record
并查看报告以查看内核中调用的内容。
kprobes 可以跟踪导致某种分配的特定内核堆栈。我自己对此不是很熟悉,但请尝试阅读附带 eBPF 脚本的示例,例如 slabratetop。
还可以在主机上稍微改变一下。添加 RAM 以确保大小合适。尝试更新的内核版本或其他发行版。