Como recarregar todos os aplicativos em execução do espaço de troca na RAM?

20

Se minha área de trabalho ficar sem memória e trocar muito, liberto ou mato o aplicativo que está desperdiçando minha RAM. Mas, depois disso, todos os meus aplicativos / área de trabalho foram trocados e são terrivelmente lentos. Você conhece uma maneira de "desassociar" (recarregar do espaço de troca na RAM) meus aplicativos / área de trabalho?

profy
fonte
Em vez de desassociar todo o sistema usando swapon/ swapoff(como sugere a resposta atualmente aceita), convém desassociar seu gerente de exibição e todos os seus filhos despejando suas memórias de processo (que forçam desassociar). Consulte também “Como forçar a troca de um processo zsh alternado?” No stackoverflow.
Zrajm

Respostas:

16

Se você realmente tiver RAM suficiente disponível novamente, poderá usar esta sequência (como root):

$ swapoff -a
$ swapon -a

(para forçar a troca explícita de todos os seus aplicativos)

(supondo que você esteja usando linux)

maxschlepzig
fonte
Mesmo se você não fizer o IIRC, ele moverá o máximo de dados possível. Embora possa danificar o cache & co. às vezes é útil.
Maciej Piechotka
18

O script python rápido e sujo a seguir despeja a memória de um processo no stdout. Isso tem o efeito colateral de carregar qualquer página trocada ou arquivo mapeado. Chame-o como cat_proc_mem 123 456 789onde os argumentos são IDs de processo.

Este script é completamente específico para Linux. Pode ser adaptável a outros sistemas com uma /procestrutura semelhante (Solaris?), Mas esqueça de executá-lo, por exemplo, * BSD. Mesmo no Linux, pode ser necessário alterar a definição c_pid_te os valores de PTRACE_ATTACHe PTRACE_DETACH. Este é um script de prova de princípio, que não serve como exemplo de boas práticas de programação. Use por sua conta e risco.

Linux disponibiliza a memória de um processo como /proc/$pid/mem. Somente determinados intervalos de endereços são legíveis. Esses intervalos podem ser encontrados lendo as informações de mapeamento de memória do arquivo de texto /proc/$pid/maps. O pseudo-arquivo /proc/$pid/memnão pode ser lido por todos os processos que têm permissão para lê-lo: o processo do leitor deve ter chamado ptrace(PTRACE_ATTACH, $pid).

#!/usr/bin/env python
import ctypes, re, sys

## Partial interface to ptrace(2), only for PTRACE_ATTACH and PTRACE_DETACH.
c_ptrace = ctypes.CDLL("libc.so.6").ptrace
c_pid_t = ctypes.c_int32 # This assumes pid_t is int32_t
c_ptrace.argtypes = [ctypes.c_int, c_pid_t, ctypes.c_void_p, ctypes.c_void_p]
def ptrace(attach, pid):
    op = ctypes.c_int(16 if attach else 17) #PTRACE_ATTACH or PTRACE_DETACH
    c_pid = c_pid_t(pid)
    null = ctypes.c_void_p()
    err = c_ptrace(op, c_pid, null, null)
    if err != 0: raise SysError, 'ptrace', err

## Parse a line in /proc/$pid/maps. Return the boundaries of the chunk
## the read permission character.
def maps_line_range(line):
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    return [int(m.group(1), 16), int(m.group(2), 16), m.group(3)]

## Dump the readable chunks of memory mapped by a process
def cat_proc_mem(pid):
    ## Apparently we need to ptrace(PTRACE_ATTACH, $pid) to read /proc/$pid/mem
    ptrace(True, int(pid))
    ## Read the memory maps to see what address ranges are readable
    maps_file = open("/proc/" + pid + "/maps", 'r')
    ranges = map(maps_line_range, maps_file.readlines())
    maps_file.close()
    ## Read the readable mapped ranges
    mem_file = open("/proc/" + pid + "/mem", 'r', 0)
    for r in ranges:
        if r[2] == 'r':
            mem_file.seek(r[0])
            chunk = mem_file.read(r[1] - r[0])
            print chunk,
    mem_file.close()
    ## Cleanup
    ptrace(False, int(pid))

if __name__ == "__main__":
    for pid in sys.argv[1:]:
        cat_proc_mem(pid)

Veja também mais informações em/proc/$pid/mem .

unswap () {
  cat_proc_mem "$@" >/dev/null
}
Gilles 'SO- parar de ser mau'
fonte
2
Essa é seriamente uma das coisas mais legais que eu já vi na troca de pilhas. Parabéns por postar isso! Há tantas boas pepitas para tirar disso.
Dan
Infelizmente, não consegui fazer esse script funcionar. No python 2, mostra erro que o valor r [0] é muito grande. No python 3 (após corrigir alguns problemas menores), recebo o OSError: [Erro 5] Erro de entrada / saída em chunk = mem_file.read (r [1] - r [0]) e o programa em que o usei trava nos dois casos.
precisa saber é o seguinte
@ Barteks2x Sinto muito, não tenho tempo agora para tornar este script à prova de erros. Funciona para mim, pelo menos em máquinas que não possuem muitas restrições de segurança (a técnica usa algumas interfaces de depuração que estão desabilitadas em configurações reforçadas). O programa é suspenso enquanto está sendo rastreado; envie-o um SIGCONT ( kill -CONT 1234onde 1234 é o PID) para continuar.
Gilles 'SO- stop being evil
@ Barteks2x: adicionei alguns erros ao verificar aqui . Isso faz com que o script funcione mesmo em IOErrors de / dev / dri / card0 e OverflowErrors de [vsyscall]. (Também imprime qual era a área do problema).
hackerb9
6

Apenas para completar, o GDB pode despejar a imagem do processo. Eu não verifiquei se ele a desassocia, mas precisa --- não há outra maneira de ler toda a memória do processo:
gdb -p $mypid
seguida por
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core

przemek
fonte
3
gcore $pidé também disponível fora do gdb (como um script pequeno)
Tobu
O gcore não tem como gravar em / dev / null, que é o que você deseja se estiver tentando forçar um processo de volta à memória. No entanto, você pode fazê-lo em um único comando assim: gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
hackerb9
0

O swapon / swapoff limpará completamente seu espaço de troca, mas você também pode liberar parte dele através do sistema de arquivos / proc. Você quer o primeiro:

# To free pagecache
echo 1 > /proc/sys/vm/drop_caches

# To free dentries and inodes
echo 2 > /proc/sys/vm/drop_caches

# To free pagecache, dentries and inodes
echo 3 > /proc/sys/vm/drop_caches

via http://linux-mm.org/Drop_Caches

Mark McKinstry
fonte
3
A memória de troca é, por definição, não cache. Descartar os caches é muito improvável que mude qualquer coisa na troca. Além disso, é preferível usar o sysctl em vez de escrever diretamente sobre os arquivos no sistema de arquivos proc. sysctl vm.drop_caches=X. Além disso, o sysctl é mais fácil de sudo.
Juliano
@julian memória virtual = ram + swap iirc. Aplicativos e caches usam memória virtual. No entanto, acho que o op precisa limpar tudo, exceto caches do swap, pois duvido que sejam realmente isso que está afetando ele.
Xenoterracide
@xenoterracide: caches só fazem sentido na memória RAM real. Não faz sentido armazenar cache no swap, eles são opostos completos. Swap é a memória lenta usada quando o sistema está com pouca memória RAM física ; cache é uma memória rápida usada quando o sistema possui bastante RAM física não utilizada .
Juliano
@ juliano sim, eu sei, mas acredito que ambos são armazenados usando memória virtual, embora seja possível que os caches sejam armazenados apenas na RAM. deixar cair honestamente os caches não faz sentido aqui, imo.
Xenoterracide