스왑 영역에서 프로세스의 모든 스왑 메모리를 제거합니다.

스왑 영역에서 프로세스의 모든 스왑 메모리를 제거합니다.

디스크에 쓰지 않고 프로세스의 모든 스왑 메모리를 스왑에서 빠르게 가져오는 방법은 무엇입니까?

이 문제를 요구하는 시스템적 문제는 다른 당사자가 해결하고 있기 때문에 이 문제의 맥락은 사소한 것입니다. 그러나 이제 문제가 생겼습니다. 로드 및 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

관련 정보