Entenda o que está acontecendo no Linux com ps, top e free

0

Estou executando meu programa java em uma máquina de thread de 12 núcleos 24. Eles têm vários processos que estão sendo executados simultaneamente. Parece que eu realizei muitos processos para que todas as tarefas tornassem a máquina muito lenta.

Aqui é a informação de topo

Tasks: 556 total,   2 running, 554 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.1%us,  0.4%sy,  0.0%ni, 63.2%id, 36.3%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  16295248k total, 16169560k used,   125688k free,     3300k buffers
Swap: 18530296k total, 10867972k used,  7662324k free,    46188k cached

Parece que meus processos são orientados para o consumo de memória, de modo que quase toda a memória foi usada por eles. Na parte superior da informação, o que eu não entendo é por que apenas duas tarefas estão sendo executadas, em vez de 23 (eu despachei 23 processos).

free -g
             total       used       free     shared    buffers     cached
Mem:            15         15          0          0          0          0
-/+ buffers/cache:         15          0
Swap:           17         10          7

Parece que toda a memória foi usada e foi trocando a máquina lenta.

ps -e -o pid,%cpu,%mem,vsz,rss,comm= --sort=vsz
29707  5.6  4.2 6268732 685660 java
29712  5.2  3.9 6268732 647352 java
...
30269  3.2  4.3 6268732 704676 java
30334  4.8  4.2 6268732 689544 java

Existem 23 desses processos java. Somando todo o% cpu, é muito próximo de 100%. Mas as principais informações indicam que a CPU não está ocupada.

Cpu(s):  0.1%us,  0.4%sy,  0.0%ni, 63.2%id, 36.3%wa,  0.0%hi,  0.0%si,  0.0%st

Eu pesquisei o tamanho de vsz e rss mas não descobri. Eu suponho que a unidade esteja no byte do quilo. Observando o vsz então os processos java estão usando 6268732kb * 23 = 144,180,836 = ~ 144gb, o que parece ser impossível colocar na RAM porque é muito mais que minha RAM (16gb), então apenas 700000kb * 23 = ~ 16gb foram colocados na memória (com a informação rss, que é a parte do armazenamento de dados na RAM). Por causa do frequente troca e troca de contexto, o sistema ficava lento.

Não sei se minha conclusão está correta ou não. Por favor, me dê alguns conselhos e como posso resolver o problema.

Adicione mais detalhes:

vmstat -a -S M
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
 2 29  16792    124   2105  13152    0    0    29    23    2    0  1  0 95  4  0

Eu não sei como devo interpretar os dados do vmstat. É um pouco estranho porque swpd: a quantidade de memória virtual usada parece alta enquanto si e so são 0.

Marcus Thornton
fonte
Parece que a troca está sendo muito usada. Observe que apenas cerca de 150 MB de RAM não estão sendo usados ​​para processos! Apesar de ter 10 GB em swap - & gt; você está com pouca memória RAM. --- Usar vmstat para ver as falhas reais da página de memória virtual ( si e so ). Usar vmstat 1 para mostrá-lo continuamente em um segundo intervalo. vmstat também mostra a atividade de IO. Usar iotop para monitoramento de atividade de IO por processo mais detalhado.
pabouk

Respostas:

0

Você sistema está claramente ausente RAM.

  • adicione mais RAM (esperando que você não precise adicionar até 128 GB)
  • Limite o número de instâncias da JVM, pois cada uma delas usa 6 GB de memória virtual.
  • ajustá-los para usar menos memória, são JVMs de 64 bits, dê uma olhada no sinalizador -Xmx.

Não há problema de CPU.

jlliagre
fonte
Então, por que somar todo o% cpu está muito próximo de 100%?
Marcus Thornton
1
Bem, eu esperaria que a soma estivesse entre 1200% e 2400% em um sistema acoplado à CPU.
jlliagre
Você quer dizer que o% está no termo de um núcleo em vez de toda a CPU do sistema?
Marcus Thornton
Em term de thread (hardware) mesmo.
jlliagre
Portanto, para a máquina de 24 linhas, a capacidade máxima de% cpu é 2400 é informação ps?
Marcus Thornton
0

Sua conclusão é de fato correta. Os tamanhos de memória estão em KB, ambos vsz e rss, como você pode verificar a si mesmo olhando a página Man para ps, na seção ESPECIFICADORES DE FORMATO PADRÃO .

Há também outra verificação que você pode executar: o rss (tamanho do conjunto de residentes, isto é a memória não-swap usada por cada processo) é de cerca de 700MB por processo. Se você tem 23 processos desse tipo, isso é bom para os 15 GB de memória usada (não swap).

Além disso, o tamanho total de sua memória física + swap é muito menor do que o requerido pela execução simultânea dessas 23 tarefas, 16 GB vs. 144 GB. Portanto, parece que nem mesmo um único processo recebe a quantidade necessária de memória neste momento.

Então quais são suas opções? Basta executar dois processos de cada vez, pois seu tamanho é tal que você pode mantê-los completamente em sua memória, sem trocar. Quando terminarem, carregue mais dois. Isso pode ser facilmente realizado com um script bash, com o comando esperar :

   my_job < file1.txt &
   my_job < file2.txt &
   wait 1 2
   my_job < file3.txt
   my_job < file4.txt
   wait 3 4....

Isso também lhe deixará algum espaço na memória para manter o / tmp, / run e assim por diante, o que significa que a capacidade do seu sistema de executar interativamente será pouco afetada.

A segunda opção (talvez a primeira), seria perguntar a si mesmo como você acabou com um código java de 7GB ... mas isso é uma pergunta para o StackOverflow

Editar:

Estou respondendo aqui ao comentário de Marcus Thornton:

Se eu puder consertar o problema de memória, ... será bom despachar todas as tarefas de uma só vez?

Sim e não. Se você corrigir o problema de memória, certamente poderá executar mais de dois trabalhos simultaneamente. Mas você consegue executar 23? Eu acho que você está superestimando a utilidade do Multi-threading . O multiencadeamento é um processador único, com dois contextos de execução, o que permite o uso paralelo de diferentes unidades funcionais no mesmo processador. Mas se as tarefas são semelhante , como eles são obrigados a estar no seu caso, eles provavelmente usarão as mesmas unidades funcionais, assim eles serão enfileirados como se não existissem multi-threading. Multi-threading não é a mesma coisa que ter processadores independentes, e permite ganhos de velocidade marginais, na melhor das hipóteses.

BTW, como você pode cpus? Você disse processadores, não cpu. O seguinte comando

  /bin/cat /proc/cpuinfo | /bin/egrep 'processor|model name|cache size|core|sibling|physical'

Ajudará você.

MariusMatutiae
fonte
VSZ (somado como 144 GB) não é certamente uma memória exigida por um processo! É o espaço de memória virtual alocado de um processo que não precisa corresponder a uma memória física alocada (arquivos de memória RAM, swap, mapeados pela memória). Esse número é, na maioria dos casos, inútil.
pabouk
Com a sua solução eu tenho que descobrir o pid de cada trabalho para que eu possa deixar a tarefa esperá-los, certo?
Marcus Thornton
@ MarcusThornton: wait é um shell embutido. Você pode usar wait %job_n ou wait pid. A maneira mais fácil seria apenas wait que aguarda todos os trabalhos em segundo plano do shell. Você não poderá usar essa solução simples se executar alguns trabalhos em segundo plano adicionais.
pabouk
1
@pabouk, Java não aloca memória física (RAM), aloca (reserva, possivelmente com supercomprometimento) memória virtual como outros processos usuais da userland. A estatística vsz é definitivamente útil, especialmente com JVMs que não tendem a reutilizar as mesmas zonas alocadas para novos objetos.
jlliagre
@MarcusThonton Sim, mas é muito fácil: depois do trabalho & amp ;, a variável de shell $! tem o PID do trabalho. Assim: job1 & amp; ; PID1 = $ !; job2 & amp; PID2 = $ !; aguarde $ PID1 $ PID2. é isso aí.
MariusMatutiae