Eu escrevi C ++ por 10 anos. Encontrei problemas de memória, mas eles poderiam ser corrigidos com uma quantidade razoável de esforço.
Nos últimos dois anos, tenho escrito C #. Acho que ainda tenho muitos problemas de memória. Eles são difíceis de diagnosticar e corrigir devido à não determinação, e porque a filosofia do C # é que você não precisa se preocupar com essas coisas quando definitivamente faz isso.
Um problema em particular que encontro é que tenho que dispor e limpar explicitamente tudo no código. Se não o fizer, os criadores de perfil de memória não ajudarão realmente, porque há tanta palha flutuando sobre você que não é possível encontrar um vazamento em todos os dados que eles estão tentando mostrar. Gostaria de saber se tenho a ideia errada ou se a ferramenta que tenho não é a melhor.
Que tipo de estratégias e ferramentas são úteis para combater vazamentos de memória no .NET?
fonte
Respostas:
Uso o MemProfiler da Scitech quando suspeito de um vazamento de memória.
Até agora, achei muito confiável e poderoso. Ele salvou meu bacon em pelo menos uma ocasião.
O GC funciona muito bem no .NET IMO, mas, como qualquer outro idioma ou plataforma, se você escreve um código incorreto, coisas ruins acontecem.
fonte
Apenas para o problema de esquecer o descarte, tente a solução descrita nesta postagem do blog . Aqui está a essência:
fonte
Usamos o software Ants Profiler Pro da Red Gate em nosso projeto. Funciona muito bem para todos os aplicativos baseados em linguagem .NET.
Descobrimos que o .NET Garbage Collector é muito "seguro" na limpeza de objetos na memória (como deveria ser). Ele manteria os objetos por perto apenas porque poderíamos usá-lo em algum momento no futuro. Isso significava que precisamos ter mais cuidado com o número de objetos que inflamos na memória. No final, convertemos todos os nossos objetos de dados em um "inflar sob demanda" (pouco antes de um campo ser solicitado) para reduzir a sobrecarga de memória e aumentar o desempenho.
Edição: Aqui está uma explicação adicional do que quero dizer com "inflar sob demanda". Em nosso modelo de objeto de nosso banco de dados, usamos Propriedades de um objeto pai para expor o (s) objeto (s) filho (s). Por exemplo, se tivéssemos algum registro que referenciasse outro registro de "detalhes" ou "pesquisa" individualmente, a estrutura seria assim:
Descobrimos que o sistema acima criou alguns problemas reais de memória e desempenho quando havia muitos registros na memória. Então, mudamos para um sistema em que os objetos eram inflados apenas quando solicitados e as chamadas ao banco de dados eram feitas apenas quando necessário:
Isso se mostrou muito mais eficiente, porque os objetos foram mantidos sem memória até serem necessários (o método Get foi acessado). Ele proporcionou um aumento de desempenho muito grande na limitação de acessos ao banco de dados e um enorme ganho em espaço na memória.
fonte
Você ainda precisa se preocupar com memória ao escrever código gerenciado, a menos que seu aplicativo seja trivial. Sugerirei duas coisas: primeiro, leia o CLR via C # porque ele ajudará você a entender o gerenciamento de memória no .NET. Segundo, aprenda a usar uma ferramenta como CLRProfiler (Microsoft). Isso pode lhe dar uma idéia do que está causando seu vazamento de memória (por exemplo, você pode dar uma olhada na fragmentação de heap de objetos grandes)
fonte
Você está usando código não gerenciado? Se você não estiver usando código não gerenciado, de acordo com a Microsoft, vazamentos de memória no sentido tradicional não serão possíveis.
A memória usada por um aplicativo pode não ser liberada, portanto, a alocação de memória de um aplicativo pode aumentar ao longo da vida útil do aplicativo.
Para lidar com esse tipo de problema, você pode implementar o IDisposable . Se você quiser ver algumas das estratégias para lidar com o gerenciamento de memória, sugiro procurar por IDisposable, XNA, gerenciamento de memória, pois os desenvolvedores de jogos precisam ter uma coleta de lixo mais previsível e, portanto, devem forçar o GC a fazer suas coisas.
Um erro comum é não remover manipuladores de eventos que se inscrevem em um objeto. Uma assinatura do manipulador de eventos impedirá que um objeto seja reciclado. Além disso, dê uma olhada na instrução using , que permite criar um escopo limitado para a vida útil de um recurso.
fonte
Este blog tem algumas orientações realmente maravilhosas usando o windbg e outras ferramentas para rastrear vazamentos de memória de todos os tipos. Excelente leitura para desenvolver suas habilidades.
fonte
Acabei de ter um vazamento de memória em um serviço do Windows que eu consertei.
Primeiro, tentei o MemProfiler . Achei muito difícil de usar e nada amigável.
Em seguida, usei o JustTrace, que é mais fácil de usar e fornece mais detalhes sobre os objetos que não são descartados corretamente.
Isso me permitiu resolver o vazamento de memória com muita facilidade.
fonte
Se os vazamentos que você está observando são devidos a uma implementação de cache em fuga, este é um cenário em que você pode considerar o uso de WeakReference. Isso pode ajudar a garantir que a memória seja liberada quando necessário.
No entanto, no IMHO, seria melhor considerar uma solução sob medida - apenas você realmente sabe quanto tempo precisa para manter os objetos por perto; portanto, projetar o código de manutenção adequado para sua situação geralmente é a melhor abordagem.
fonte
Prefiro dotmemory de Jetbrains
fonte
Big guns - Ferramentas de depuração para Windows
Esta é uma incrível coleção de ferramentas. Você pode analisar montes gerenciados e não gerenciados com ele e pode fazê-lo offline. Isso foi muito útil para depurar um de nossos aplicativos ASP.NET que continuava reciclando devido ao uso excessivo de memória. Eu só tive que criar um despejo de memória completo do processo em execução no servidor de produção, todas as análises foram feitas offline no WinDbg. (Verificou-se que alguns desenvolvedores estavam usando demais o armazenamento de sessões na memória.)
O blog "Se quebrado está ..." tem artigos muito úteis sobre o assunto.
fonte
A melhor coisa a ter em mente é acompanhar as referências aos seus objetos. É muito fácil acabar com referências suspensas a objetos com os quais você não se importa mais. Se você não vai mais usar algo, livre-se dele.
Acostume-se a usar um provedor de cache com vencimentos deslizantes, para que, se algo não for referenciado por uma janela de tempo desejada, ele seja desreferenciado e limpo. Mas se estiver sendo acessado muito, dirá na memória.
fonte
Uma das melhores ferramentas é usar o Debugging Tools for Windows e fazer um despejo de memória do processo usando o adplus ; em seguida, use o windbg e o plugin sos para analisar a memória do processo, os threads e as pilhas de chamadas.
Você também pode usar esse método para identificar problemas nos servidores, depois de instalar as ferramentas, compartilhar o diretório e conectar-se ao compartilhamento pelo servidor usando (net use) e fazer uma pane ou travar o processo.
Então analise offline.
fonte
Após uma das minhas correções para o aplicativo gerenciado, tive a mesma coisa, como verificar se meu aplicativo não terá o mesmo vazamento de memória após a minha próxima alteração, por isso escrevi algo como a estrutura de Verificação de Liberação de Objeto. o pacote NuGet ObjectReleaseVerification . Você pode encontrar uma amostra aqui https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample e informações sobre essa amostra http://outcoldman.ru/en/blog/show/322
fonte
No Visual Studio 2015, considere usar a ferramenta de diagnóstico pronta para uso da memória para coletar e analisar dados de uso da memória.
A ferramenta Uso da memória permite tirar um ou mais instantâneos do heap de memória gerenciada e nativa para ajudar a entender o impacto no uso de memória dos tipos de objeto.
fonte
uma das melhores ferramentas que usei no DotMemory. você pode usar essa ferramenta como uma extensão do VS. Depois de executar o aplicativo, você pode analisar todas as partes da memória (por Objeto, NameSpace, etc.) que o aplicativo usa e tirar algumas fotos dele Compare-o com outros SnapShots. DotMemory
fonte