web-dev-qa-db-ja.com

Linuxカーネルがスラブメモリを解放できないのはなぜですか?

私は、平凡なことでもスワップに到達し、結果としてかなり応答しなくなるポイントに達するまで、メモリ使用量が増加し続けているシステムを使用しています。犯人はカーネルに割り当てられたメモリであるように見えますが、カーネルで何が起こっているのか正確に理解するのに苦労しています。

どのカーネルスレッド/モジュール/カーネルメモリ使用量の特定のチャンクに責任があるかをどのようにして知ることができますか?

時間の経過に伴うシステムのメモリ使用量のグラフを次に示します。

System memory usage; slab_unrecl grows over time

時間とともに増加するslab_unrecl値は、/proc/meminfoSUnreclaimフィールドに対応します。

そのグラフの終わりに向かって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

結論:

  • カーネルのスラブアロケーターは約2.3 GBのRAMを使用しています
  • そのほとんどすべてが取り返しのつかない
  • 約1.3 GBがkmem_cacheキャッシュによって占有されています
  • 別の0.5 GBは、さまざまなサイズのkmallocキャッシュに属します

これは私が壁にぶつかったところです。私はそれらのキャッシュの内部をどのように調べ、なぜそれらが非常に大きくなったのか(またはなぜそれらのメモリが解放されないのか)を理解していません。調査をさらに進めるにはどうすればよいですか?

3
asciiphil

perf kmem record --slabはプロファイリングデータをキャプチャし、perf kmem stat --slab --callerはカーネルシンボルごとに小計されます。

ただし、ワークロードがこれを行う理由は説明されていません。加える perf recordおよびレポートを見て、カーネルに何が呼び出されているかを確認します。

kprobeは、特定の割り当てにつながる特定のカーネルスタックをトレースできます。私自身はこれに精通していませんが、 slabratetopのようなeBPFスクリプトに付随する例 を読んでみてください。

また、ホストの状況を少し変えてください。 RAMを追加して、サイズが不足していないことを確認してください。新しいカーネルバージョンまたは別のディストリビューションを試してください。

3
John Mahowald