slab_unreclaimableメモリは、Linuxメモリ管理でスラブアロケーターによって割り当てられ、unreclaimableとしてマークされたメモリです。 slab_unreclaimableメモリが総メモリの高い割合を占めると、使用可能なメモリの量が減少し、システムのパフォーマンスが低下します。 このトピックでは、Alibaba Cloud Linuxを実行するElastic Compute Service (ECS) インスタンス上のslab_unreclaimableメモリの割合が高い原因を特定する方法について説明します。
問題の説明
Linuxインスタンスでcat /proc/meminfo | grep "SUnreclaim"
コマンドを実行してSUnreclaim値を表示すると、SUnreclaim値が大きいことがわかります (たとえば、SUnreclaim: 6069340 kB
) 。 スラブ再生不能メモリがメモリ全体の10% を超えると、スラブメモリがリークする可能性があります。
原因
Linuxメモリ管理では、カーネルはスラブをキャッシングメカニズムとして使用して、メモリの小さなチャンクを効率的に割り当てます。 カーネルコンポーネントまたはドライバは、メモリ割り当てAPI (kmallocなど) を呼び出すことによってスラブアロケータからメモリを要求しますが、メモリを適切に解放しないため、使用可能なメモリが少なくなります。
トラブルシューティングの手順
slab_unreclaimableメモリの割合が高いLinuxインスタンスに接続します。
詳細については、「接続方法の概要」をご参照ください。
次のコマンドを実行して、最大数の
オブジェクト
または最大量のメモリを持ち、メモリを再利用できないスラブの名前を確認します。objects
の数が最も多い、またはメモリ量が最も多いスラブに関する情報を表示します。slabtop -s -a
コマンド出力では、
OBJ /slab
列で最大値を持つスラブの名前 (name
列の値) を表示および記録できます。次のコマンドを実行して、スラブメモリが再利用可能かどうかを判断します。
次のコマンドで、
<slab NAME>
を、前のステップで取得した、OBJ /slab
列の最大値を持つスラブの名前に置き換えます。cat /sys/kernel/slab/<slab NAME>/reclaim_account
たとえば、次のコマンドを実行して、
kmalloc-192
という名前のスラブにreclimableとマークされたメモリがあるかどうかを判断できます。cat /sys/kernel/slab/kmalloc-192/reclaim_account
スラブメモリが再生不能な場合は、コマンド出力に0が表示されます。 スラブメモリが再生可能な場合、コマンド出力に1が表示されます。
slab_unreclaimableメモリの割合が高い原因を特定します。
クラッシュツールを使用して静的に分析したり、perfツールを使用して問題を動的に分析し、スラブメモリリークの原因を特定したりできます。 このトピックのシナリオ例では、
kmalloc-192
という名前のスラブにメモリリークがあります。方法1: クラッシュを使用して静的解析を実行
次のコマンドを実行して、クラッシュツールをインストールします。
sudo yum install crash -y
次のコマンドを実行して、kernel-debuginfoツールをインストールします。
Alibaba Cloud Linux 3
sudo yum install -y kernel-debuginfo-<kernel version> -- enableepo=alinux3-plus-debug
説明kernel version
をシステムの実際のカーネルバージョンに置き換えます。uname -r
コマンドを実行して、カーネルのバージョンを照会します。Alibaba Cloud Linux 2
sudo yum install kernel-debuginfo -y
次のコマンドを実行して、クラッシュツールを起動します。
sudo crash
crashで次のコマンドを実行して、
kmalloc-192
に関するメモリ統計を表示します。kmem -S kmalloc-192
大量のメモリ統計データが利用可能な場合は、最後の数行のみを表示するように指定できます。 たとえば、次のコマンドを実行して、データの最後の10行を表示できます。
kmem -S kmalloc-192 | tail -n 10
サンプルコマンド出力:
SLAB MEMORY NODE TOTAL ALLOCATED FREE ffffea004c94e780 ffff88132539e000 0 42 29 13 ffffea004cbef900 ffff88132fbe4000 0 42 40 2 ffffea000a0e6280 ffff88028398a000 0 42 40 2 ffffea004bfa8000 ffff8812fee00000 0 42 41 1 ffffea006842b380 ffff881a10ace000 0 42 41 1 ffffea0009e7dc80 ffff880279f72000 0 42 34 8 ffffea004e67ae80 ffff881399eba000 0 42 40 2 ffffea00b18d6f80 ffff882c635be000 0 42 42 0
コマンドの出力は、
ffff88028398a000
の空きメモリ量 (free
列の値) が少なく、割り当てられたメモリ量 (allocated
列の値) が大きいことを示します。クラッシュ時に次のコマンドを実行して、
ffff88028398a000
に関するメモリデータを表示します。rd ffff88028398a000 512 -S
コマンド出力に大量のデータが含まれている場合は、コマンド出力をページ単位で表示できます。
たとえば、
put_cred_rcu
関数がコマンド出力で複数回繰り返される場合、Linuxカーネルのソースコードを確認し、put_cred_rcu
関数を検索できます。void __put_cred(struct cred * cred) { call_rcu(&cred->rcu, put_cred_rcu); }
カーネルのcred構造にスラブメモリリークがある場合、
put_cred_rcu
関数を使用して資格情報を非同期に解放し、cred構造の最後に表示されます。
方法2: perfを使用して動的解析
次のコマンドを実行してperfツールをインストールします。
sudo yum install perf -y
次のコマンドを実行してperfを使用し、200秒間隔で
kmalloc-192
にリリースされていないメモリを動的に取得します。sudo perf record -a -e kmem:kmalloc --filter 'bytes_alloc == 192' -e kmem:kfree --filter ' ptr != 0' sleep 200
動的に取得したデータをカレントディレクトリの一時ファイルに保存します。
この例では、動的に取得されたデータは、testperf.txtという名前の一時ファイルに保存されます。 以下のコマンドを実行します。
sudo perf record -a -e kmem:kmalloc --filter 'bytes_alloc == 192' -e kmem:kfree --filter ' ptr != 0' sleep 200
次のコマンドを実行して、testperf.txtの内容を表示します。
cat testperf.txt
空きメモリがない (
free
) スラブメモリを手動で特定し、Linuxカーネルのソースコードでスラブメモリリークの原因となる関数を手動で照会する必要があります。
クラッシュやperfなどのツールを使用して、メモリリークに関連する関数呼び出しパスまたは影響を受けるカーネルデータ構造を特定した後、カーネル開発者または専門のO&M担当者の指導の下、メモリリークの特定の原因を特定し、メモリリークの問題を解決することをお勧めします。
問題を解決するには、次の操作を実行します。
カーネルまたはパッチをアップグレードします。
カーネルパラメータを調整します。
影響を受けるサービスまたはモジュールを再起動します。
アプリケーションまたはドライバを最適化します。
システムを再起動します。
関連ドキュメント
スラブメモリリークにより、インスタンスで実行されているビジネスで使用可能なメモリの減少、メモリの断片化、メモリ不足 (OOM) キラーの問題、およびシステムパフォーマンスのジッターが発生した場合は、次の操作を実行します。