Назад | Перейти на главную страницу

Почему мое ядро ​​Linux не может освободить свою блочную память?

У меня есть система, которая страдала от постоянно увеличивающегося использования памяти, пока не достигла точки, когда она запускала подкачку даже для повседневных вещей и, следовательно, перестала отвечать. Похоже, что виновата была память, выделенная ядром, но мне трудно понять, что именно происходит в ядре.

Как я могу узнать, какие потоки / модули ядра / что-то еще отвечают за определенные фрагменты использования памяти ядра?

Вот график использования памяти системой с течением времени:

В 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

Выводы:

Здесь я наткнулся на стену. Я не понял, как заглянуть внутрь этих кешей и понять, почему они стали такими большими (или почему их память не подлежит возврату). Как я могу продолжить свои расследования?

perf kmem record --slab будет собирать данные профилирования и perf kmem stat --slab --caller будет подытог по символу ядра.

Однако это не объясняет, почему ваша рабочая нагрузка делает это. Добавить в perf record и просмотрите отчет, чтобы узнать, что вызывает ядро.

kprobes может отслеживать определенные стеки ядра, ведущие к определенному типу распределения. Я сам не очень знаком с этим, но попробуйте прочитать примеры, сопровождающие скрипты eBPF, такие как slabratetop.

Также немного измените вещи на вашем хосте. Добавьте оперативную память, чтобы убедиться, что вы не занижаете ее размер. Попробуйте более новые версии ядра или другой дистрибутив.