O que são bytes privados, bytes virtuais, conjunto de trabalho?


491

Estou tentando usar o utilitário perfmon windows para depurar vazamentos de memória em um processo.

É assim que a perfmon explica os termos:

Conjunto de Trabalho é o tamanho atual, em bytes, do Conjunto de Trabalho deste processo. O Conjunto de Trabalho é o conjunto de páginas de memória recentemente tocadas pelos threads no processo. Se a memória livre do computador estiver acima de um limite, as páginas serão deixadas no conjunto de trabalho de um processo, mesmo que não estejam em uso. Quando a memória livre cai abaixo de um limite, as páginas são cortadas em Conjuntos de trabalho. Se necessário, eles sofrerão uma falha suave no conjunto de trabalho antes de deixar a memória principal.

Bytes virtuais é o tamanho atual, em bytes, do espaço de endereço virtual que o processo está usando. O uso do espaço de endereço virtual não implica necessariamente o uso correspondente das páginas de disco ou de memória principal. O espaço virtual é finito e o processo pode limitar sua capacidade de carregar bibliotecas.

Bytes particulares é o tamanho atual, em bytes, de memória que esse processo alocou e não pode ser compartilhado com outros processos.

Estas são as perguntas que tenho:

São os Bytes Privados que devo medir para ter certeza de que o processo está apresentando algum vazamento, pois não envolve bibliotecas compartilhadas e, caso ocorra algum vazamento, se ocorrer, virá do próprio processo?

Qual é a memória total consumida pelo processo? São os Bytes Virtuais ou a soma dos Bytes Virtuais e do Conjunto de Trabalho?

Existe alguma relação entre bytes privados, conjunto de trabalho e bytes virtuais?

Existem outras ferramentas que dão uma idéia melhor do uso da memória?


3
Uma ferramenta melhor seria valgrind / Helgrind, mas não no Windows, infelizmente :(
kornel kisielewicz

É o byte privado que devo medir para ter certeza de que o processo está com algum vazamento? Se os bytes privados de um processo não crescem, não há vazamentos de memória. Se eles crescerem, pode ser devido a vazamentos de memória e a fragmentação da memória. Eu acho que é difícil dizer olhando para o crescimento de bytes privados o que isso significa exatamente.

@SergeiKurenkov Uma coisa que podemos dizer é que NUNCA seria devido à "fragmentação da memória".
21718 Jamie Hanrahan #

Respostas:


517

A resposta curta para essa pergunta é que nenhum desses valores é um indicador confiável de quanta memória um executável está realmente usando, e nenhum deles é realmente apropriado para depurar um vazamento de memória.

Bytes privados referem-se à quantidade de memória que o processo executável solicitou - não necessariamente à quantidade que está realmente usando . Eles são "privados" porque (geralmente) excluem arquivos mapeados na memória (ou seja, DLLs compartilhadas). Mas - aqui está o problema - eles não excluem necessariamente a memória alocada por esses arquivos . Não há como saber se uma alteração nos bytes particulares ocorreu devido ao próprio executável ou a uma biblioteca vinculada. Os bytes privados também não são exclusivamente memória física; eles podem ser paginados para o disco ou na lista de páginas em espera (ou seja, não estão mais em uso, mas ainda não foram paginados).

Conjunto de Trabalho refere-se à memória física total (RAM) usada pelo processo. No entanto, diferentemente dos bytes privados, isso também inclui arquivos mapeados na memória e vários outros recursos, por isso é uma medida ainda menos precisa do que os bytes privados. Esse é o mesmo valor que é relatado no "Mem Usage" do Gerenciador de Tarefas e tem sido a fonte de inúmeras quantidades de confusão nos últimos anos. A memória no conjunto de trabalho é "física" no sentido de que pode ser tratada sem uma falha de página; no entanto, a lista de páginas em espera também ainda está fisicamente na memória, mas não é relatada no Conjunto de Trabalho, e é por isso que você pode ver o "Uso da Memória" cair repentinamente quando você minimiza um aplicativo.

Bytes virtuais são o espaço total de endereços virtuais ocupado por todo o processo. É como o conjunto de trabalho, no sentido de incluir arquivos mapeados na memória (DLLs compartilhadas), mas também inclui dados na lista de espera e dados que já foram paginados e estão em um arquivo de paginação no disco em algum lugar. O total de bytes virtuais usados ​​por todos os processos em um sistema sob carga pesada adicionará significativamente mais memória do que a máquina realmente possui.

Portanto, os relacionamentos são:

  • Bytes particulares são o que seu aplicativo realmente alocou, mas incluem o uso de arquivo de paginação;
  • Conjunto de trabalho são os bytes privados não paginados e os arquivos mapeados na memória;
  • Bytes virtuais são o conjunto de trabalho mais bytes privados paginados e lista de espera.

Há outro problema aqui; Assim como as bibliotecas compartilhadas podem alocar memória dentro do seu módulo de aplicativo, levando a possíveis falsos positivos relatados nos bytes privados do seu aplicativo , seu aplicativo também pode acabar alocando memória dentro dos módulos compartilhados , levando a falsos negativos . Isso significa que é realmente possível para o seu aplicativo ter um vazamento de memória que nunca se manifesta nos bytes privados. Improvável, mas possível.

Bytes particulares são uma aproximação razoável da quantidade de memória que seu executável está usando e podem ser usados ​​para ajudar a restringir uma lista de possíveis candidatos a um vazamento de memória; se você vê o número crescendo e crescendo constantemente e infinitamente, você deve verificar se há um vazamento nesse processo. Isso não pode, no entanto, provar que existe ou não um vazamento.

Uma das ferramentas mais eficazes para detectar / corrigir vazamentos de memória no Windows é, na verdade, o Visual Studio (o link vai para a página usando VS para vazamentos de memória, não para a página do produto). O Rational Purify é outra possibilidade. A Microsoft também possui um documento de práticas recomendadas mais gerais sobre esse assunto. Existem mais ferramentas listadas nesta pergunta anterior .

Espero que isso esclareça algumas coisas! Rastrear vazamentos de memória é uma das coisas mais difíceis de fazer na depuração. Boa sorte.


26
Receio que sua resposta não esteja correta. Bytes particulares referem-se à quantidade de memória (RAM) solicitada pelo processo executável - não apenas à memória física. Assim, você certamente pode inspecionar a maioria dos casos de vazamento de memória monitorando bytes privados. Tente :: VisualAlloc para confirmar uma grande parte da memória (por exemplo, 1.5G). Você poderá ver que seus bytes particulares são muito maiores que o conjunto de trabalho. O que prova que o seu "Conjunto de trabalho são bytes particulares mais arquivos mapeados na memória" está incorreto.
Jay Zhu

4
Na verdade, acredito que o entendimento de gravação é "Conjunto de Trabalho é o Bytes Privados na memória mais os arquivos mapeados na Memória". E Bytes Privados PODEM ser trocados - você pode ver bytes privados maiores que a memória física que você possui na máquina.
Jay Zhu

2
@Aaronaught: Sua primeira declaração sobre indicador confiável e apropriado para depuração é confusa. Bytes particulares é um indicador confiável de vazamento no espaço de memória do aplicativo. Pode ser uma DLL dependente e indireta, mas é um vazamento no espaço de memória do aplicativo. Você pode explicar por que não pode ser usado para depuração? um despejo de memória completo do processo do aplicativo deve nos dizer o que está consumindo essa memória. Não sei ao certo por que ele não pode ser usado para depuração. Você pode lançar alguma luz?
precisa saber é o seguinte

@ G33kKahuna: Não está claro para mim como um despejo de memória diria o que está consumindo a memória em qualquer sentido significativo - a menos que com "o que" você quer dizer "quais módulos", mas tudo o que você tem é um instantâneo, você ainda não consiga ver qual módulo está realmente vazando a memória ao longo do tempo, a menos que você faça várias descargas ao longo do tempo e sob condições rigorosamente controladas. É difícil conceber uma estratégia de depuração mais ineficiente e não confiável. Os criadores de perfil estão em toda parte nos dias de hoje; use um.
Aaronaught 30/01

1
Execute um objsize completo !, isso deve mostrar todos os objetos fixados na pilha imediata. Você pode confirmar marcando o eeheap -gc. Isso deve mostrar onde o volume está parado. Normalmente, se nenhuma dica estiver disponível com todos os comandos acima, seus bytes particulares serão consumidos por objetos não coletados no GC. Agora vá para gchandles ou gcleaks. Esses comandos devem informar quais tipos / endereço do objeto não podem ser mapeados. O ponteiro ainda está lá, mas o objeto se foi. Esse é um problema categórico para manipuladores de eventos não lançados.
G33kKahuna

10

Você não deve tentar usar perfmon, gerenciador de tarefas ou qualquer outra ferramenta para determinar vazamentos de memória. Eles são bons para identificar tendências, mas não muito mais. Os números relatados em termos absolutos são muito vagos e agregados para serem úteis para uma tarefa específica, como detecção de vazamento de memória.

Uma resposta anterior a esta pergunta deu uma ótima explicação sobre quais são os vários tipos.

Você pergunta sobre uma recomendação de ferramenta: eu recomendo o Validador de memória. Capaz de monitorar aplicativos que fazem bilhões de alocações de memória.

http://www.softwareverify.com/cpp/memory/index.html

Isenção de responsabilidade: projetei o Validador de memória.


1
Não consigo nem executar um arquivo de classe simples (em Java)? O que da?
Jn1kk

Eu suspeito que Stephen e diabo estão de alguma forma relacionados ou mesmo clonado ...: D;)
Robert Koritnik

@StephenKellett, existe uma versão de teste?
Pacerier

@Pacerier Se você seguir o link, há uma avaliação para as versões x86 e x64 logo acima da opção de compra à esquerda da página.
Bradley A. Tetreault

10

A definição dos contadores de perfmon foi quebrada desde o início e, por algum motivo, parece ser muito difícil de corrigir.

Uma boa visão geral do gerenciamento de memória do Windows está disponível no vídeo " Mistérios do gerenciamento de memória revelado " no MSDN: abrange mais tópicos do que o necessário para rastrear vazamentos de memória (por exemplo, gerenciamento de conjuntos de trabalho), mas fornece detalhes suficientes nos tópicos relevantes.


Para lhe dar uma dica do problema com as descrições do contador perfmon, aqui está a história interna sobre bytes privados de " Private Bytes Performance Counter - Beware! " No MSDN:

P: Quando um Byte Privado não é um Byte Privado?

A: Quando não é residente.

O contador de bytes privados relata a cobrança de confirmação do processo. Ou seja, a quantidade de espaço que foi alocada no arquivo de troca para reter o conteúdo da memória privada no caso de ela ser trocada. Nota: Estou evitando a palavra "reservado" devido a uma possível confusão com a memória virtual no estado reservado que não foi confirmada.


Do " Planejamento de desempenho " no MSDN:

3.3 Bytes particulares

3.3.1 Descrição

Memória privada, é definida como memória alocada para um processo que não pode ser compartilhado por outros processos. Essa memória é mais cara que a memória compartilhada quando vários desses processos são executados em uma máquina. A memória privada nas DLLs não gerenciadas (tradicionais) geralmente constitui uma estatística estática do C ++ e é da ordem de 5% do conjunto de trabalho total da DLL.


1
voto positivo por causa dos exemplos insanamente bons de como está quebrado!
Bruno Brant

A primeira citação está errada. A alocação de "bytes privados" não exige que nada seja "alocado no arquivo de troca" (que é realmente chamado de arquivo de paginação). Você nem precisa ter um arquivo de paginação para que "bytes privados" sejam alocados. De fato, a alocação de bytes privados não usa imediatamente nenhum espaço em qualquer lugar e nem sempre pode usar tanto quanto foi alocado.
21718 Jamie Hanrahan #

A segunda citação não é muito melhor. Os bytes particulares usados ​​no código DLL não são necessariamente alocados estaticamente na DLL. O código DLL é perfeitamente gratuito para chamar VirtualAlloc, HeapAlloc (malloc e new no CRTL) etc. Ele também tenta descrever o tamanho da memória privada como uma porcentagem do tamanho do conjunto de trabalho, o que não faz sentido. O primeiro é um tamanho virtual (e será o mesmo para todo uso do código com a mesma entrada), enquanto o último é físico (que pode ser radicalmente diferente de uma execução para a seguinte, dependendo da quantidade de memória ou - faminto a máquina é).
21718 Jamie Hanrahan #

5

Há uma discussão interessante aqui: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ Meu entendimento desse segmento é que liberar pequenas alocações é não refletido em bytes particulares ou conjunto de trabalho.

Longa história curta:

se eu ligar

p=malloc(1000);
free(p);

os bytes privados refletem apenas a alocação, não a desalocação.

se eu ligar

p=malloc(>512k);
free(p);

os bytes privados refletem corretamente a alocação e a desalocação.


7
Isso é explicado pelo fato de as funções de memória da biblioteca padrão C usarem um Heap personalizado ou Win32, que é um mecanismo de gerenciamento de memória sobre o gerenciamento de memória de nível de processo de nível inferior.
Kyberias

@ Kyberias, então como chegamos abaixo disso?
Pacerier

enquanto (1) livre (malloc (1000)); // Isso faria com que os bytes privados aumentassem para sempre?
franckspike

2
@franckspike: não, aumentará para um determinado ponto (geralmente cerca de 4 kB, mas isso pode variar) e depois parará, porque o CRT reutilizará a memória liberada anteriormente em vez de solicitar novas páginas do sistema operacional.
Miral

@ Pacerier: Você pode ligar para VirtualAlloc e VirtualFree.
Jamie Hanrahan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.