Como alguém iria rapidamente puxar toda a memória trocada de um processo para fora do swap sem gravar no disco?
O contexto sobre esta questão é trivial, já que a questão sistêmica que requer a questão está sendo tratada por outras partes. No entanto, neste momento, tenho um problema em que frequentemente tenho que liberar espaço de troca em um nó OpenVZ, enquanto o carregamento e a espera de IO são extremamente altos.
A troca é geralmente consumida principalmente por um pequeno número de processos MySQL e clamd sendo executados em contêineres individuais. Reiniciar esses serviços libera a troca e resolve o problema no nó, mas é indesejável por razões óbvias.
Estou procurando uma maneira de liberar rapidamente a troca desses processos enquanto o nó está sobrecarregado e precisa de algo mais rápido do que o meu método atual:
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
Este core dump força todo o RAM a ser acessado e, portanto, faz o trabalho de retirá-lo do swap, mas eu ainda não encontrei uma maneira de evitar que ele seja gravado. Além disso, parece que o processo seria mais rápido se eu pudesse isolar os intervalos de endereços que estão atualmente trocados e apenas descarregar essa parte para / dev / null, mas ainda não encontrei uma maneira de fazer isso.
Este é um nó enorme, então o método usual swapoff / swapon é proibitivamente demorado, e novamente, a configuração do nó não está sob meu controle, então consertar a causa raiz não faz parte desta questão. No entanto, qualquer insight sobre como eu poderia liberar uma porção significativa de swap rapidamente sem matar / reiniciar qualquer coisa seria apreciado.
Ambiente: CentOS 6.7 / OpenVZ
Atualização para qualquer um que possa se deparar com isso mais tarde:
Usando a entrada de Jlong, criei a seguinte função:
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;};
É um pouco lento, mas faz exatamente o que foi solicitado aqui. Provavelmente poderia melhorar a velocidade encontrando apenas os maiores intervalos de endereços em swap e omitindo as iterações para as áreas trivialmente pequenas, mas a premissa é sólida.
Exemplo de trabalho:
#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
Solução final para o despejo em massa apenas dos grandes blocos de memória trocados:
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
Ainda estou para determinar se esse método representa algum risco para a integridade do processo ou do sistema, especialmente quando em loop em vários processos simultaneamente. Se alguém tiver conhecimento de qualquer efeito potencial que isso possa ter nos processos ou no sistema, sinta-se à vontade para comentar.