Gerenciamento de Memória
Carlos dos Santos
CDS Software
Microsoft MVP
Microsoft Regional Director
carlos@cds-software.com.br
www.cds-software.com.br
@cdssoftware
• Mais de 25 anos de experiência no desenvolvimento de software
• Responsável por Pesquisa e Desenvolvimento na CDS Informática
• Microsoft MVP desde 2008
• Microsoft Regional Director
• Um dos criadores do projeto open source CodeCracker: www.github.com/code-cracker
• Mantenedor do projeto open source BoletoNet: www.github.com/boletonet
• Blog: www.carloscds.net
• GitHub: www.github.com/carloscds
www.gotaskfly.com
www.gotaskfly.com
www.gotaskfly.com
www.gotaskfly.com
http://pinvoke.net
www.gotaskfly.com
www.gotaskfly.com
www.gotaskfly.com
www.gotaskfly.com
Stack Heap
x = 0
int x = 0;
www.gotaskfly.com
Stack Heap
cli: Cliente Codigo:1 | Nome: “Carlos”
Cliente cli = new Cliente();
cli.Codigo = 1;
cli.Nome = “Carlos”;
www.gotaskfly.com
www.gotaskfly.com
www.gotaskfly.com
www.gotaskfly.com
• Cada processo tem seu próprio espaço de endereço virtual separado. Todos os processos no mesmo computador
compartilham a mesma memória física e arquivo de paginação, se houver algum.
• Como desenvolvedor de aplicativos, você trabalha apenas com o espaço de endereço virtual e nunca manipula a
memória física diretamente. O coletor de lixo aloca e libera memória virtual para você no heap gerenciado.
• Condições para coleta de lixo (GC):
• O sistema tem pouca memória física. Isso é detectado pela notificação de falta de memória do sistema operacional.
• A memória usada por objetos alocados no heap gerenciado ultrapassa o limite aceitável. Esse limite é ajustado
continuamente enquanto o processo é executado.
• O método GC.Collect() é chamado. Em quase todos os casos, você não precisa chamar esse método porque o coletor de
lixo funciona continuamente. Esse método é usado principalmente para situações exclusivas e testes.
• Chamar o GC.Collect() não indica que a memória será coletada naquele momento
www.gotaskfly.com
• O heap está organizado em gerações de modo que possa manipular objetos de vida útil longa e curta. A coleta
de lixo ocorre principalmente com a recuperação de objetos de vida útil curta, que geralmente ocupam apenas
uma pequena parte do heap. Há três gerações de objetos no heap:
• Geração 0. Essa é a geração mais jovem e contém objetos de vida útil curta. Um exemplo de um objeto de
vida útil curta é uma variável temporária. A coleta de lixo ocorre com mais frequência nessa geração.
• Geração 1. Essa geração contém objetos de vida útil curta e serve como um buffer entre objetos de vida útil
curta e longa. Normalmente passou pelo GC e por ter espaço no heap permaneceu.
• Geração 2. Essa geração contém objetos de vida útil longa. Um exemplo de um objeto de vida útil longa é
um objeto em um aplicativo para servidores que contém dados estáticos que estão vivos durante o
processo.
• Dicas:
• Use sempre Dispose(), trabalhe com using {}
• Não fique chamando o GC.Collect(), ele sabe quando precisa rodar!!!
• Cuidado com objetos não gerenciados: PInvoke
www.gotaskfly.com
• Vamos imaginar que temos 5 objetos criados – Gen 0:
• Agora o GC inicia e libera os objetos 1, 3 e 5 e move 2 e 4 para o início, enquanto criamos 6, 7, 8, 9 e 10. Ficamos
então com 2 e 4 na Gen 1 e o restante em Gen 0:
• Novamente o GC inicia, coletando alguns objetos, enquanto criamos novos:
• Imaginamos que a Gen 1 está cheia:
• Então os objetos “sobreviventes” da Gen 1 vão para Gen 2, e temos memória livre:
1 2 3 4 5
2 4 6 7 8 9 10
2 4 6 7 10 11 12 13 14 15
2 6 10 13 15 16 17 18 19 20
2 6 10 13 17 18 20
Gen 0 Gen 1 Gen 2
www.gotaskfly.com
• Boxing é o processo de conversão de ValueType para o tipo object, e Unboxing é o inverso.
• Veja no exemplo abaixo, a variável valor (inteiro) é boxed para obj (object):
• O objeto pode ser então unboxed para int:
Stack Heap
valor = 0
obj = valor; int: 0
int valor = 0;
object obj = valor;
obj = 100;
valor = (int)obj;
www.gotaskfly.com
• Ao chamar uma classe que implementa a interface IDisposable, teremos o método Dispose(), que é chamado
pelo GC.
• Utilizamos o Dispose() para liberar recursos não mais utilizados, principalmente não gerenciados.
• Utilizar o método using {} automaticamente chama o Dispose()
• GC.SuppressFinalize() indica para o GC que o objeto já foi “limpo” e não precisa ser coletado.
www.gotaskfly.com
• Variáveis estáticas não são coletadas pelo GC.
• Ela existem durante toda a execução da aplicação.
• Potencialmente perigosas em aplicações web, pois podem compartilhar dados entre as sessões.
www.gotaskfly.com
• Evite concatenação de strings, para isto use o StringBuilder.
• StringBuilder é muito mais rápido e eficiente.
www.gotaskfly.com
• System.Span<T> é um novo tipo de valor no .NET.
• Permite a representação de regiões contíguas de memória!
• Não importa se a memória está associada a um objeto gerenciado, foi fornecida por código nativo por interop
ou está na pilha.
• E ele faz isso oferecendo acesso seguro com características de desempenho semelhantes às das matrizes.
www.gotaskfly.com
www.gotaskfly.com
• Degradação de performance ao longo do tempo – memory leak
• Problemas com escalabilidade, mais usuários, mais problemas (obs: você faz teste de carga?)
• Memoria não melhora mesmo reiniciando a aplicação – objetos temporários
• Como verificar este tipo de problema:
• Visual Studio Profiler
• Perfmon do Windows
• WinDbg
www.gotaskfly.com
www.gotaskfly.com
Demo
www.gotaskfly.com
Obrigado!
Carlos dos Santos
CDS Software
carlos@cds-software.com.br
www.carloscds.net
@cdssoftware

Gerenciamento de Memória

  • 1.
    Gerenciamento de Memória Carlosdos Santos CDS Software Microsoft MVP Microsoft Regional Director carlos@cds-software.com.br www.cds-software.com.br @cdssoftware
  • 2.
    • Mais de25 anos de experiência no desenvolvimento de software • Responsável por Pesquisa e Desenvolvimento na CDS Informática • Microsoft MVP desde 2008 • Microsoft Regional Director • Um dos criadores do projeto open source CodeCracker: www.github.com/code-cracker • Mantenedor do projeto open source BoletoNet: www.github.com/boletonet • Blog: www.carloscds.net • GitHub: www.github.com/carloscds
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
    www.gotaskfly.com Stack Heap cli: ClienteCodigo:1 | Nome: “Carlos” Cliente cli = new Cliente(); cli.Codigo = 1; cli.Nome = “Carlos”;
  • 12.
  • 13.
  • 14.
  • 15.
    www.gotaskfly.com • Cada processotem seu próprio espaço de endereço virtual separado. Todos os processos no mesmo computador compartilham a mesma memória física e arquivo de paginação, se houver algum. • Como desenvolvedor de aplicativos, você trabalha apenas com o espaço de endereço virtual e nunca manipula a memória física diretamente. O coletor de lixo aloca e libera memória virtual para você no heap gerenciado. • Condições para coleta de lixo (GC): • O sistema tem pouca memória física. Isso é detectado pela notificação de falta de memória do sistema operacional. • A memória usada por objetos alocados no heap gerenciado ultrapassa o limite aceitável. Esse limite é ajustado continuamente enquanto o processo é executado. • O método GC.Collect() é chamado. Em quase todos os casos, você não precisa chamar esse método porque o coletor de lixo funciona continuamente. Esse método é usado principalmente para situações exclusivas e testes. • Chamar o GC.Collect() não indica que a memória será coletada naquele momento
  • 16.
    www.gotaskfly.com • O heapestá organizado em gerações de modo que possa manipular objetos de vida útil longa e curta. A coleta de lixo ocorre principalmente com a recuperação de objetos de vida útil curta, que geralmente ocupam apenas uma pequena parte do heap. Há três gerações de objetos no heap: • Geração 0. Essa é a geração mais jovem e contém objetos de vida útil curta. Um exemplo de um objeto de vida útil curta é uma variável temporária. A coleta de lixo ocorre com mais frequência nessa geração. • Geração 1. Essa geração contém objetos de vida útil curta e serve como um buffer entre objetos de vida útil curta e longa. Normalmente passou pelo GC e por ter espaço no heap permaneceu. • Geração 2. Essa geração contém objetos de vida útil longa. Um exemplo de um objeto de vida útil longa é um objeto em um aplicativo para servidores que contém dados estáticos que estão vivos durante o processo. • Dicas: • Use sempre Dispose(), trabalhe com using {} • Não fique chamando o GC.Collect(), ele sabe quando precisa rodar!!! • Cuidado com objetos não gerenciados: PInvoke
  • 17.
    www.gotaskfly.com • Vamos imaginarque temos 5 objetos criados – Gen 0: • Agora o GC inicia e libera os objetos 1, 3 e 5 e move 2 e 4 para o início, enquanto criamos 6, 7, 8, 9 e 10. Ficamos então com 2 e 4 na Gen 1 e o restante em Gen 0: • Novamente o GC inicia, coletando alguns objetos, enquanto criamos novos: • Imaginamos que a Gen 1 está cheia: • Então os objetos “sobreviventes” da Gen 1 vão para Gen 2, e temos memória livre: 1 2 3 4 5 2 4 6 7 8 9 10 2 4 6 7 10 11 12 13 14 15 2 6 10 13 15 16 17 18 19 20 2 6 10 13 17 18 20 Gen 0 Gen 1 Gen 2
  • 18.
    www.gotaskfly.com • Boxing éo processo de conversão de ValueType para o tipo object, e Unboxing é o inverso. • Veja no exemplo abaixo, a variável valor (inteiro) é boxed para obj (object): • O objeto pode ser então unboxed para int: Stack Heap valor = 0 obj = valor; int: 0 int valor = 0; object obj = valor; obj = 100; valor = (int)obj;
  • 19.
    www.gotaskfly.com • Ao chamaruma classe que implementa a interface IDisposable, teremos o método Dispose(), que é chamado pelo GC. • Utilizamos o Dispose() para liberar recursos não mais utilizados, principalmente não gerenciados. • Utilizar o método using {} automaticamente chama o Dispose() • GC.SuppressFinalize() indica para o GC que o objeto já foi “limpo” e não precisa ser coletado.
  • 20.
    www.gotaskfly.com • Variáveis estáticasnão são coletadas pelo GC. • Ela existem durante toda a execução da aplicação. • Potencialmente perigosas em aplicações web, pois podem compartilhar dados entre as sessões.
  • 21.
    www.gotaskfly.com • Evite concatenaçãode strings, para isto use o StringBuilder. • StringBuilder é muito mais rápido e eficiente.
  • 22.
    www.gotaskfly.com • System.Span<T> éum novo tipo de valor no .NET. • Permite a representação de regiões contíguas de memória! • Não importa se a memória está associada a um objeto gerenciado, foi fornecida por código nativo por interop ou está na pilha. • E ele faz isso oferecendo acesso seguro com características de desempenho semelhantes às das matrizes.
  • 23.
  • 24.
    www.gotaskfly.com • Degradação deperformance ao longo do tempo – memory leak • Problemas com escalabilidade, mais usuários, mais problemas (obs: você faz teste de carga?) • Memoria não melhora mesmo reiniciando a aplicação – objetos temporários • Como verificar este tipo de problema: • Visual Studio Profiler • Perfmon do Windows • WinDbg
  • 25.
  • 26.
  • 27.
    www.gotaskfly.com Obrigado! Carlos dos Santos CDSSoftware carlos@cds-software.com.br www.carloscds.net @cdssoftware