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 .
Tags performance swap memory linux