Pergunta

Estou tentando medir o uso de memória de um processo (um programa Java) no Linux e tenho duas dúvidas relacionadas a isso:

  1. Eu tentei usar o script ps_mem.py(soma valores de /proc/$PID/smaps) e o pico de uso total de memória foi de cerca de 135 MB (memória privada e compartilhada).A quantidade de memória compartilhada é inferior a 1 MB.Tentando usar Valgrind com a ferramenta massif valgrind --tool=massif --trace-children=yes --stacks=yes java myProgram rende cerca de 10 MB no pico de uso de memória.
    Agora pelo que entendi, heap é onde as variáveis ​​do meu programa são armazenadas, isso significa que a diferença entre os dois métodos é o espaço ocupado pelo próprio código (incluindo o jvm)?

  2. O mesmo programa usa quantidades diferentes de memória em máquinas diferentes se elas tiverem quantidades diferentes de RAM e/ou usarem processadores diferentes (ARM ou x86)?

Foi útil?

Solução

  1. Depende.
    • Muitos dos mapeamentos de memória compartilhada em smaps são apoiados diretamente por bibliotecas/binários no disco.Embora o tamanho delas seja importante, é menos importante, pois o sistema pode descartar essas páginas a qualquer momento e recarregá-las do disco quando necessário novamente.
    • Qualquer coisa suja ou privada pertence exclusivamente ao processo atual (bem, árvore de processos se o seu programa for bifurcado sem executivos).Isso é mais importante porque o sistema deve salvá-los para troca se precisar retirar essas páginas da memória.
    • O que o maciço está medindo provavelmente está correlacionado com este último.Porém, a memória ocupada pela própria JVM (sem o seu programa) está em ambos.
  2. Sim.Java ou uma biblioteca que ele usa pode ajustar seu modelo de memória dependendo do tamanho da RAM disponível.Em uma arquitetura diferente, você está usando binários completamente diferentes, que podem ser maiores ou menores ou organizados de maneira diferente ou usando estratégias diferentes para JIT e gerenciamento de memória.

Outras dicas

Há uma pergunta semelhante além desta e respondendo a mesma aqui para que as pessoas saibam como as informações do linux proc stat vm atualmente não são precisas.
Valgrind pode mostrar informações detalhadas, mas retarda significativamente o aplicativo de destino e, na maioria das vezes, altera o comportamento do aplicativo.

Presumo que o que todos querem saber sobre o "uso de memória" do WRT é o seguinte ...
No Linux, a quantidade de memória física que um único processo pode usar pode ser dividida aproximadamente nas seguintes categorias.

  • M.uma memória mapeada anônima
    • .p privado
      • .d sujo == heap malloc/mmapped e pilha alocada e memória gravada
      • .c clean == heap malloc/mmapped e memória de pilha uma vez alocada, gravada e liberada, mas ainda não recuperada
    • .s compartilhado
      • .d sujo == não deveria haver nenhum
      • .c limpo == não deveria haver nenhum
  • M.n memória mapeada nomeada
    • .p privado
      • .d sujo == arquivo mapeado na memória escrita privada
      • .c clean == programa mapeado/texto da biblioteca mapeado privado
    • .s compartilhado
      • .d sujo == arquivo mapeado memória escrita compartilhada
      • .c clean == texto da biblioteca mapeada compartilhado mapeado

Eu preferiria obter os números da seguinte maneira para obter os números reais com menos sobrecarga.
Você tem que resumir isso para dividir o que ps mostra como RSS e obter números mais precisos para não confundir.
/proc/(pid)/status tenta mostrar esses números, mas eles estão falhando.
Então, em vez de tentar rotular [anon], [Stack], corretamente para cada mapeamento, meu desejo é que o povo do kernel do Linux mainline o código de entrada do Proc para soma e mostre esses MAPD, MAPC, MNPD, ....números.
Pessoas com Linux incorporado ficarão muito felizes, IMHO.

Mapa:

 awk '/^[0-9a-f]/{if ($6=="") {anon=1}else{anon=0}} /Private_Dirty/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps

Mapa:

 awk '/^[0-9a-f]/{if ($6=="") {anon=1}else{anon=0}} /Private_Clean/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps

M.n.p.d:...e assim por diante

Para o nº 1, memória compartilhada é a memória (potencialmente) usada por mais de um processo.Isso ocorre basicamente se você executar o mesmo arquivo binário em vários processos ou se processos diferentes estiverem usando uma biblioteca compartilhada.O heap é onde a memória alocada é armazenada (quando você usa new em Java).Como o Java tem sua VM, ele aloca muita memória no nível do processo que você não vê no seu código Java.Acho que sim, a maior parte desses 135 MB vem do próprio código/dados da JVM.No entanto, há também a memória ocupada pela pilha (quando você faz uma chamada de função e tem variáveis ​​locais).

Para o número 2, uma quantidade diferente de RAM não afetaria a quantidade de "memória" usada quando deixamos a memória igual a RAM + espaço de troca.No entanto, processadores diferentes (especialmente se estamos falando de 32 bits vs.64 bits) pode usar uma quantidade diferente de memória.Além disso, a maneira como um processo é compilado pode alterar a quantidade de memória usada porque você pode instruir um compilador a otimizar o consumo de memória em relação à velocidade, bem como desabilitar parte ou toda a otimização por completo.

Você pode querer dar uma olhada no JConsole.As coisas podem ser complicadas dependendo do propósito da sua medição.Se você quiser saber o uso de memória do seu programa Java, as ferramentas que medem o uso da memória de um processo serão imprecisas porque mostrarão a memória usada pela JVM e também pelo seu programa.

Quanto à ferramenta massif, você deve saber que partes da JVM serão armazenadas na pilha, e o próprio código java pode estar no heap (já que é uma variável da JVM), não sei o suficiente sobre a JVM para dizer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top