Fala galeros, como vocês estão? Apesar da correria eu estou bem, hoje vou iniciar mais uma série aqui no blog, “.NET O Que você Não Vê!”, abordando assuntos não tão falados, porém quase obrigatórios para todo desenvolvedor .NET.
No primeiro artigo vou trazer um tema teórico, porém ESSENCIAL para o processo de desenvolvimento de qualquer software, entender o que é Heap e Stack e como se dividem esses 2 tipos de memória.
…
Como funciona uma aplicação?
Vamos lá, antes de entender esses 2 tipos de memória, precisamos entender como funciona uma aplicação quando ela está rodando.
Então quando você realiza o deploy e usa sua aplicação seja em um servidor, dispositivo móvel ou até desktop o que acontece é o seguinte, parte da sua aplicação sobe para a memória RAM do dispositivo.
Logo, cada ação que você executa da mais simples a mais complexa, seja login, mudar de tela ou até mesmo enviar um texto o processador PRECISA BUSCAR informações que estão nas memórias, seja ela memória registradora, cache, RAM ou disco rígido, porém não irei me aprofundar em tipos de memória de dispositivos e nem em CLR (terá um artigo só para isso).
Em resumo, seu processador precisa armazenar informações temporariamente para fazer as determinadas funções do seu software, para isso ele acessa a memória RAM.
Porém não é simplesmente acessar e usar os valores, você tem valores mais pesados e mais leves de serem processados, para ter um melhor gerenciamento de memória o .NET divide a memória em 2 partes, Heap e Stack!
Basicamente nossa aplicação fica como o desenho abaixo.
…
Stack e Value Types
Ótimo, relembramos como basicamente funciona uma aplicação quando está em memória, caso você ainda esteja confuso com isso recomendo estudar um pouco sobre arquitetura da informação, sistemas operacionais e o básico sobre estrutura de dados.
Vou começar explicando a memória Stack, acredito que ela seja a mais simples de entender.
Bom como você viu no desenho anterior, o espaço em memória dedicado a memória stack é beeeeem menor do que o da memória heap, e isso tem um motivo.
Basicamente a memória stack é onde ficam as variáveis de tipos primitivos do C#, são elas, int, float, decimal, structs, ponteiros etc.
Como a memória stack tem bem menos capacidade de memória ela é muito eficiente para armazenar tipos primitivos, que são muito leves!
Então quando você tem.
Basicamente a variável salário fica armazenada da seguinte forma.
Logo, quando o processador precisa do valor de salário, ele acessa esse valor diretamente da memória stack, e isso é chamado de Value Type ou tipos de valores, pois o acesso é direto ao endereço de memória onde está aquele valor!
Em resumo, a memória stack armazena valores de tipos primitivos e Value Types são os valores armazenados na memória stack que são acessadas “direto” pelo processador.
Bom você ter ficado com a seguinte dúvida: porque então não armazenar todos os valores na memória stack já que ela é rápida?
A memória stack é pequena, aproximadamente entre 1MB, o fato dela ser pequena torna rápida a ação do processador buscar um valor lá dentro, porém no C# assim como todas as linguagens somente tipos primitivos não são o suficiente, com isso temos tipos mais pesados, nossas classes!
Caso as classes fossem armazenadas na memória stack teríamos um problema, caso a memória alocada para elas fosse maior que 1MB (pode ser alterado pelo SO) teríamos uma exceção de overflow de memória ou StackOverflowException.
…
Ponteiros
Antes de partirmos para a memória heap precisamos entender o BÁSICO sobre ponteiros.
Vou tentar ser breve pois ponteiros é um assunto que tem uma certa abrangência e para nosso cenário precisamos somente do básico, novamente, se esse termo para você é novo, recomendo estudar sobre estrutura de dados e arquitetura da informação.
Em resumo quando temos um ponteiro, temos um valor armazenado na memória APONTANDO para outro endereço de memória onde está armazenado o valor desejado.
Ok, mas e quando isso é efetivo, não seria melhor acessar diretamente o endereço de memória?
Depende, se o valor desejado for um tipo primitivo realmente não tem tanto sentido utilizar ponteiros, porém quando nosso valor é um objeto complexo com N tipos primitivos é mais performático e eficaz transitar o endereço de memória pela aplicação e acessar somente quando necessário do que ficar passando bytes e bytes de um lado para outro.
…
Heap e Reference Types
Bom entendemos um pouco sobre ponteirose memória stack, porém ficou faltando uma lacuna, se a memória stack armazena somente tipos primitivos, quem armazena nossos tipos complexos?
Se você respondeu memória Heap, você está certo, mas vamos entender isso direito.
Lembre-se, a memória stack é pequena e tipos complexos (coleções e objetos) são pesados, logo eles ficam armazenados na memória heap!
Ok Lucas, mas você não disse que a memória heap é lenta? Sim, pelo fato dela ser grande, buscar um valor dentro dela se torna um processo lento para o processador e não é gargalo que queremos.
Por isso usamos os reference types, basicamente guardamos o endereço de memória do objeto e ou coleção que queremos na memória stack e quando o processador precisar desses valores ele já sabe EXATAMENTE onde eles estão na memória Heap.
Por fim, quando utilizamos a palavra NEW para instanciar um objeto, armazenamos ele na memória heap e guardamos o ponteiro para o endereço de memória dele na memória stack, assim o processador consegue gerenciar sem problemas itens leves e pesados!
Então imagine que temos o seguinte código.
O objeto pessoa é armazenado da seguinte forma na memória.
Em resumo, a memória heap armazena objetos complexos e coleções, para acessar esses objetos e coleções o processador acessa um reference type ou ponteiro (identificado pelo *) onde ele contém o exato endereço de memória onde os valores estão armazenados na memória heap.
…
Conclusão
Ufa que artigo longo, espero que a partir de agora você consiga identificar quando um valor fica na memória stack e quando ele fica na heap e principalmente como o C# gerencia os valores nessas duas memórias, esse é um dos conceitos mais importantes para qualquer desenvolvedor C# .NET.
Agradeço a atenção e bons estudos!!!!!
Caso precise entrar em contato, me mande uma mensagem aqui.
AVISO
Minha nova plataforma já está em construção! irá conter todos os recursos dessa plataforma, cursos pagos e gratuitos, treinamentos, mentorias e muito mais, caso queira ter acesso antecipado (gratuito) e ser um dos primeiros a testar me mande um email em lucas.eschechola@outlook.com, obrigado!