Quanto de memória estou utilizando?

É comum muitos programadores, inclusive eu, há algum tempo atrás, medirem o consumo de memória de uma aplicação pelo gerenciador de tarefas do windows, o que é, na melhor das hipóteses, uma maneira incompleta de realizar essa verificação. O gerenciador de tarefas na verdade mostra a quantidade de memória que ele alocou naquele momento e não o quanto de memória o programa utiliza, além do que, o Windows contabiliza a memória alocada que foi utilizada e liberada até que outro programa a utilize.

Exemplo: seu programa utilizou 4.569K e liberou 169K, esse valor é contabilizado pelo windows até que outro programa o utilize (o gerenciador continua mostrando os 4.569K).

A causa desse problema com o gerenciador de tarefas é o gerenciador de memória runtime do Delphi alocar memória indiretamente. Quando o programa solicita memória para o gerenciador, ele aloca blocos de memória para o programa. Os blocos tem tamanho fixo de modo que para cada pedido de memória o gerenciador aloca a quantidade necessária de blocos contínuos para satisfazer o pedido do programa.

Deste ponto de vista o bloco é a menor quantidade de bytes que o gerenciador aloca.

Exemplo: Um bloco tem 16 bytes; se o programa pede 4 bytes, o gerenciador irá alocar um bloco; se o programa pedir 18 bytes, o gerenciador irá alocar dois blocos.

Parece que o gerenciador está “torrando” memória a toa, mas isso é feito para evitar a fragmentação da memória. Quando o programa devolve memória ao gerenciador, este não a devolve para o Windows, pois ele deduz que o programa pode solicitar mais memória a qualquer momento e a reserva para otimizar o tempo de acesso a ela.

Entendendo melhor o funcionamento:

Imagine que você possui duas classes (TAlocaMemoriaAtoa e TAlocaMemoriaAVontade). Quando executamos um programa qualquer, por exemplo, vamos imaginar que o gerenciador aloque 10 blocos de memória. Após isso criamos a classe TAlocaMemoriaAtoa que solicita ao gerenciador mais 10 blocos. O tamanho total de memória utilizada é 20 blocos. Ao destruírmos a classe TAlocaMemoriaAtoa o sistema libera 10 blocos, mas o gerenciador os mantém disponíveis para a aplicação. Se nesse momento criarmos a classe TAlocaMemoriaAVontade e esta solicita 5 blocos de memória, o gerenciador buscará 5 blocos dos 10 reservados anteriormente, quando a classe TAlocaMemoriaAtoa fora destruída.

BINGO! Por isso que quando eu fazia debug da minha aplicação com o gerenciador de tarefas aberto os “Free” e “FreeAndNil” quase nunca funcionavam! :)

No meu próximo post falarei sobre gerenciadores de memória alternativos como o FastMM, adotado como gerenciador de memória padrão na versão 2006 do Delphi, e faremos alguns testes comparativos. Até a próxima.


4 comentários em 'Quanto de memória estou utilizando?' »

Assine os comentários usando RSS ou faça um TrackBack para 'Quanto de memória estou utilizando?'.

[-]
[+]

Em 26 de janeiro de 2007 às 14:36

Trabalho com o FastMM em uma aplicação web (Intraweb) e o mesmo foi a salvação p/ eliminar uma menssagem “chata” q aparecia quando os recursos da máquina (escassez de memória) estavam saturados naquele instante.

 
[-]
[+]
Edson de Lima disse,

Em 26 de janeiro de 2007 às 19:37

Hoje mesmo me deparei com esse efeito. Fiquei um tempão imaginando o que poderia ser, pois acredito ter tomado todos os cuidados para não haver vazamento de memória. E não tinha descoberto a razão descobri até ler esse artigo :)

 
[-]
[+]
Andre D.B disse,

Em 12 de fevereiro de 2007 às 16:36

Muito interessante é útil!

 
[-]
[+]
Jean disse,

Em 17 de maio de 2007 às 11:29

Estou tendo um problema muito estranho! Fiz uma aplicação simples com Delphi 7 e banco de dados Oracle XE. Coloquei um botão na tela que apenas ativa um timer e este realiza uma abertura de dataset a cada 10 ms. Olhando pelo gerenciador do windows a memória utilizada é cada vez maior. O fato é que está muito dificil de achar o problema. Tentei usar o FastMM mas ao sair da aplicação a mensagem que apareceu na tela não identifica onde está o furo de memória. O que posso fazer? A mensagem que aparece é: “61 – 68 bytes: TWideStringList x 20″

Um abraço