Muita gente já ouviu afirmações do tipo “Flash é pesado!”, sem saber exatamente o porquê. Na maioria das vezes, a culpa é do desenvolvedor que, por não saber como o player funciona e não se preocupar em manter boas práticas de programação, acaba sobrecarregando a RAM e CPU. Tentarei explicar como podemos otimizar nossas aplicações, mas antes, vamos entender o que acontece por trás.

Antigamente, o player não tinha o costume de consumir muita RAM, o problema recaía no uso pesado do processador (que melhorou com o Player 10, que começa a usar recursos da placa de vídeo) mas temos uma série de novos recursos (ByteArray, BitmapData…) que podem consumir muitos megas da memória. Além disso, desde o ActionScript 2 o Garbage Collector (GC) do flash tem dificuldades em manter a RAM limpa, pelo próprio modo como as referências internas são feitas, como explicado pelo Jim Corbett neste vídeo em (25:30):

Mas afinal, o que é o Garbage Collector e como ele funciona?

O GC é o processo que limpa a sujeira que você deixou pra trás: ele retira da memória objetos que não serão mais usados pela aplicação. E como ele fica sabendo disso? Bem, atualmente isso é feito no flash de duas maneiras distintas: Reference Counting e Mark Sweep.

O mais simples dos métodos, o Reference Counting era usado desde o Actionscript 1.0, e a idéia é bem prática: toda vez que alguém faz referência a um objeto (ou seja, provavelmente será usado), um contador de uso do objeto é acrescido de 1. Toda vez que uma referência é retirada, esse contador é decrescido de 1. Desse modo, quando não há nada fazendo referência ao objeto (o contador voltou a 0), ele é marcado para ser retirado da memória. Exemplo:

var obj1:Object = {var1:"oi"}; // contador em 1, o objeto está sendo referenciado por obj1
var obj2:Object = obj1; // contador em 2
delete obj1; // contador em 1, não está mais sendo referenciado por obj1
trace( obj2.var1 ); // retorna "oi". Como pode ver, o objeto e referências a ele são coisas distintas
delete obj2; // contador em 0. aqui o objeto é alvo do GC para remoção

Algumas observações:
- Como podem ver, o objeto e a variável que guarda o objeto são coisas distintas. Mesmo se não houver nada fazendo referência a { var1:”oi” }, ele não deixa de existir. Por isso a importância do Garbage Collector.
- Quando ninguém mais “fala sobre” o objeto (referência a variáveis, escutas de evento, enterFrames…), é uma justificativa para ele ser jogado fora. Mas podem haver casos onde o objeto é referenciado, mas não é mais usado.

Pense no seguinte cenário: A guarda B, B guarda C e C guarda A. No final das contas, pode ocorrer o caso de nenhum deles ser mais utilizado, mas todos estão sendo referenciados no código, logo não serão retirados da memória. Para corrigir esse problema, outra técnica é utilizada: o Mark Sweep. Nesse método, o flash percorre a partir do root todos os objetos que consegue encontrar, recursivamente, e os marca. Se algum objeto não for marcado, significa que ele não está sendo utilizado. No caso que falei acima, se nem A nem B nem C tiverem uma ligação direta ou indireta com a raiz da aplicação, eles serão removidos da memória.

Note que limpar a memória é um processo lento, que percorre todos os objetos, logo não é acionado com tanta frequência: aproximadamente uma vez a cada 60 segundos ou quando a alocação de memória der um pulo maior que 20% o uso atual (dados não oficiais). De qualquer modo, não é previsível quando um objeto vai ou não ser removido da memória. Note que, enquanto o objeto existir, isso quer dizer que os loops, acessos a arquivos, sons, etc, continuação ser processados, então fica evidente a importância de se saber como manter a memória limpa.

Em meu próximo post tentarei explicar como podemos ajudar o GC do flash em seu trabalho.

referências:
http://blogs.eyepartner.com/adrian/flex/flex-tip-6-garbage-collection-in-flex/GC Flush em Flex

http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html gskinner falando sobre o GC


No Responses to “Otimizando suas aplicações - entendendo o GarbageCollector”  

  1. No Comments

Leave a Reply