Como carregar toda a memória do processo de swap rapidamente (linux)?

4

Eu corri um monte de processos com muita CPU em paralelo; eles normalmente usam alguns GB de memória cada. De tempos em tempos eles alocam grande quantidade de memória também (digamos 150-250 GB). Normalmente, no máximo, um dos processos faz isso, então eles se encaixam na RAM disponível (384GB na minha máquina). No entanto, às vezes acontece que mais deles alocam essa grande quantidade ao mesmo tempo e (obviamente) tudo fica mais lento por causa da troca.

Nesses casos, paro todos os processos, exceto um, que permitem que ele seja computado de forma eficaz. Mas leva muito tempo para trocar um processo parado, já que significa carregar dezenas de gigabytes do disco em um padrão de acesso aleatório. Portanto, a questão é: como posso forçar um único processo a carregar sequencialmente todo o núcleo do swap?

Até agora eu só encontrei uma dica de kernel swappiness, que (com a ajuda de cgroups) pode impedir que um processo troque mais, mas não ajuda no desempenho de descompactação. Desligar todo o swap obviamente não é possível, já que os outros processos parados precisam ocupar espaço lá.

Criar meu próprio mini-programador também não é uma opção - os processos são vários scripts / programas pequenos em python e os picos de memória geralmente acontecem em chamadas de bibliotecas, portanto não posso prever quando ocorrerá um pico.

Só para deixar claro: não considero a compra de terabytes de RAM, a essa escala é muito caro. Colocar o swap no array SSD / SSD ajudará apenas um pouco (medido), então também não é uma solução que estou procurando.

(auto-resposta parcial):

Parece que a leitura de troca realmente sequencial (apenas as páginas que pertencem ao processo único) é dificilmente possível sem o kernel hacking: eu medi swapoff -a e certamente não li swap sequencialmente. E seria lógico lê-lo mais rapidamente se essa otimização fosse fácil de implementar.

Atualmente, minha melhor abordagem é ler toda a memória do processo através de /proc/[pid]/mem pseudo-file usando o script abaixo (que deve ser executado como root):

#!/usr/bin/python2
import re
import sys
pid=str(sys.argv[1]) # process pid given by the first arg

print(pid) # just to aviod mistakes

CHUNKSIZE=10485760  # single read() invocation block size

total=0
maps_file = open("/proc/"+pid+"/maps", 'r')
mem_file = open("/proc/"+pid+"/mem", 'r', 0)
for line in maps_file.readlines():  # for each mapped region
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    if m.group(3) == 'r':  # if this is a readable region
        start = int(m.group(1), 16)
        end = int(m.group(2), 16)
        mem_file.seek(start)  # seek to region start
        togo = end-start # number of bytes to read
        while togo > CHUNKSIZE: # read sequential memory from region one block at the moment
            mem_file.read(CHUNKSIZE) 
            togo -= CHUNKSIZE
            total += CHUNKSIZE
            print(total/1048576) # be verbose, print megabytes read so far
        mem_file.read(togo) # read remaining region contents
        total+=togo # dump contents to standard output
        print(total/1048576) # be verbose...
maps_file.close()
mem_file.close()

Ocorre falha nos últimos bytes de memória, mas geralmente funciona com o mesmo desempenho que swapoff e carrega apenas o processo determinado. Script é um snippet modificado de esta resposta .

    
por bzaborow 29.01.2016 / 09:09

0 respostas