スワップ領域からプロセス内のすべてのスワップメモリ​​を削除します。

スワップ領域からプロセス内のすべてのスワップメモリ​​を削除します。

ディスクに書き込まずにプロセス内のすべてのスワップメモリ​​をスワップからすばやくインポートする方法は?

この問題を必要とするシステム的問題は他の当事者が解決しているため、この問題の文脈は些細なものです。しかし、今問題が発生しました。負荷とIOの待ち時間が非常に高い場合、OpenVZノードでスワップスペースを確保する必要があることがよくあります。

スワップは通常、単一のコンテナで実行される少数の MySQL および clamd プロセスによって主に使用されます。これらのサービスを再起動すると、スワップを解放し、ノードの問題を解決することができますが、明確な理由でお勧めできません。

ノードが過負荷になり、現在の方法よりも高速な方法が必要な場合に、これらのプロセスのスワップをすばやく解放する方法を探しています。

unswap(){ [[ $1 && $(ls /proc/$1/maps) ]]  && ((gcore -o /tmp/deleteme $1 &>/dev/null; rm -fv /tmp/deleteme.$1)&) 2>/dev/null  || echo "must provide valid pid";};unswap

このコアダンプは、すべてのメモリへのアクセスを強制し、スワップから取得する操作を実行しますが、ファイルに書き込まない方法を見つけることができませんでした。また、現在交換されているアドレス範囲を切り離してその部分を/ dev / nullにダンプできる場合、プロセスはより速いようですが、まだこれを行う方法が見つかりませんでした。

これは巨大なノードなので、一般的なswapoff / swaponメソッドは時間がかかり、ノード構成を制御できないため、根本的な原因を解決することはこの問題の一部ではありません。しかし、何も終了したり再開したりせずに、ほとんどのスワップスペースをすばやく確保する方法について教えてください。

環境: CentOS 6.7/OpenVZ

後でこの問題を誤って発見できる人のためのアップデート:

Jlongの入力を使って次の関数を作成しました。

unswap(){ (awk -F'[ \t-]+' '/^[a-f0-9]*-[a-f0-9]* /{recent="0x"$1" 0x"$2}/Swap:/&&$2>0{print recent}' /proc/$1/smaps | while read astart aend; do gdb --batch --pid $1 -ex "dump memory /dev/null $astart $aend" &>/dev/null; done&)2>/dev/null;};

少し遅いですが、ここで要求したタスクを正確に実行します。交換の中で最大のアドレス範囲だけを探し、小さな領域の反復を省略することで速度を向上させることができますが、これは合理的な場合にのみ可能です。

実際のケース:

#Find the process with the highest swap use
[~]# grep VmSwap /proc/*/status 2>/dev/null | sort -nk2 | tail -n1 | while read line; do fp=$(echo $line | cut -d: -f1); echo $line" "$(stat --format="%U" $fp)" "$(grep -oP "(?<=NameS).*" $fp); done | column -t
/proc/6225/status:VmSwap:   230700  kB  root  mysqld

#Dump the swapped address ranges and observe the swap use of the proc over time
[~]# unswap(){ (awk -F'[ t-]+' '/^[a-f0-9]*-[a-f0-9]* /{recent="0x"$1" 0x"$2}/Swap:/&&$2>0{print recent}' /proc/$1/smaps | while read astart aend; do gdb --batch --pid $1 -ex "dump memory /dev/null $astart $aend" &>/dev/null; done&)2>/dev/null;}; unswap 6225; while true; do grep VmSwap /proc/6225/status; sleep 1; done
VmSwap:   230700 kB
VmSwap:   230700 kB
VmSwap:   230676 kB
VmSwap:   229824 kB
VmSwap:   227564 kB
... 36 lines omitted for brevity ... 
VmSwap:     9564 kB
VmSwap:     3212 kB
VmSwap:     1876 kB
VmSwap:       44 kB
VmSwap:        0 kB

大量のスワップメモリ​​の塊だけを一括ダンプする最終的なソリューション:

unswap(){ (awk -F'[ \t-]+' '/^[a-f0-9]*-[a-f0-9]* /{recent="0x"$1" 0x"$2}/Swap:/&&$2>1000{print recent}' /proc/$1/smaps | while read astart aend; do gdb --batch --pid $1 -ex "dump memory /dev/null $astart $aend" &>/dev/null; done&)2>/dev/null;}; grep VmSwap /proc/*/status 2>/dev/null | sort -nk2 | tail -n20 | cut -d/ -f3 | while read line; do unswap $line; done;echo "Dumps Free(m)"; rcount=10; while [[ $rcount -gt 0 ]]; do rcount=$(ps fauxww | grep "dump memory" | grep -v grep | wc -l); echo "$rcount        $(free -m | awk '/Swap/{print $4}')"; sleep 1; done 

特に、同時に複数のプロセスを繰り返すと、この方法がプロセスまたはシステムの状態に危険をもたらすかどうかはまだ確認されていません。これがプロセスやシステムに与える可能性のある潜在的な影響を知っている人がいる場合は、いつでもコメントしてください。

ベストアンサー1

GDBの「dump memory」コマンドを使用して/ dev / nullに書き込むと、同じ結果が得られます。

あなたがしなければならないのは、/proc/$PID/smapsでunswapが必要な領域を見つけることだけです。 /proc/$PID/smaps の例:

02205000-05222000 rw-p 00000000 00:00 0 
Size:              49268 kB
Rss:               15792 kB
Pss:                9854 kB
Shared_Clean:          0 kB
Shared_Dirty:      11876 kB
Private_Clean:         0 kB
Private_Dirty:      3916 kB
Referenced:          564 kB
Anonymous:         15792 kB
AnonHugePages:         0 kB
Swap:              33276 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB

次に、--batchモードを使用してgdbコマンドを実行すると、関数で使用できます。

[root@nunya ~]# swapon -s ; gdb --batch --pid 33795 -ex "dump memory /dev/null 0x02205000 0x05222000" ;swapon -s
Filename                Type        Size    Used    Priority
/dev/sda2                               partition   7811068 7808096 -1

[Thread debugging using libthread_db enabled]

Filename                Type        Size    Used    Priority
/dev/sda2                               partition   7811068 7796012 -1

おすすめ記事