Gerenciamento de memória e tamanho dos arquivos em grandes aplicativos utilizando o Modules do Flex 2.0.1

Sistemas realmente grandes feitos em Flex tendem a ficar com um tamanho em Kbytes igualmente grande. Além disso, com um sistema tão grande, é bem provável que os usuários utilizem apenas parte dele. Assim, o usuário ter de carregar o sistema inteiro para poder utilizá-lo não é uma idéia coerente.

Já no Flex 1.5 em aplicativos muito grande nós utilizávamos o componente Loader para carregar aplicativos (no caso de um portal) ou módulos de aplicativos, de acordo com a necessidade do usuário.

Mas nem sempre a banda e a quantidade de dados transferida é um problema (em casos em que o aplicativo só funcionará em redes locais, por exemplo): as vezes o vilão da vez pode ser o consumo de memória.

Quem já utilizou o SWFLoader para carregar um outro aplicativo em Flex pode ter notado que na verdade o aplicativo nunca é totalmente descarregado da memória (veja: um aplicativo Flex, e não um simples filme SWF), e o pior: tantas forem as vezes que este aplicativo for “carregado” via SWFLoader, tantas vezes ele irá para a memória! (aliás, vale notar que o objetivo aqui não é criticar o Flash Player no tocante ao uso de memória. Seu garbage collector faz um ótimo trabalho, mas os objetos têm de estar disponíveis para tal).

Nessa situação, o uso do ViewStack traz um ótimo benefício: nenhuma das telas será carregada duas vezes na memória, já que simplesmente uma tela é escondida e outra é revelada. O consumo de memória não irá crescer, não haverá telas duplicadas instânciadas, mas o tamanho do arquivo total será muito grande.

Mas o que fazer quando as duas questões, memória e tamanho dos arquivos, se tornam um problema e devem ser consideradas?

Muitas pessoas (eu incluso) acharam que a funcionalidade de Module no Flex 2.0.1 era a resposta simples e fácil que procurávamos, no estilo “instalar-e-usar”, mas não é bem assim. Além da funcionalidade ser similar (o ModuleLoader funciona do mesmo modo que o SWFLoader) e ambos serem baseados no mesmo componente do Flash (o

1
flash.display.Loader

), o problema sobre o não real descarregamento da memória está muito mais ligado à natureza do Flash e do Flex SDK (que é muito inter-dependente entre si).

Pensando nisso que trabalhei em uma simples abordagem hibrída com Modules (para separar os módulos em diferentes arquivos que serão carregados apenas uma vez) e com o ViewStack (para incremento nulo de memória ao mostrar uma tela que já foi mostrada anteriormente).

A idéia é simples: um ViewStack de ModuleLoaders e um pequeno código para verificar se o Modulo já foi anteriormente carregado. Assim, caso isso seja verdadeiro, o ViewStack apenas mostra o módulo; caso contrário é feito o download do módulo e este atribuído como um dos filhos do ViewStack. Tantas vezes quanto um módulo for exibido, não haverá incremento na memória.

stackedmodule_samples_memory.png

O gráfico acima mostra o desempenho de quatro abordagens (embora o StackedModules tenha sido criado depois desse estudo) em relação ao consumo de memória para uma aplicação de demonstração. Tanto o SWFLoader quando o ModuleLoader puro e simples têm um desempenho similar. As interações 4, 5 e 6 são de carregamento de um módulo (ou aplicativo no caso do SWFLoader) já carregado anteriormente. Note que o consumo de memória continua crescendo nessas interações, diferente do uso do ViewStack e do StackedModules. Esse gráfico faz parte de um estudo sobre essas abordagens em uma aplicação de exemplo. Os valores são médias aritméticas de pelo menos duas medições.

stackedmodule_samples_transferred.png

Resolvido o problema de memória com a abordagem do StackedModules (inserindo os módulos carregados como filhos do ViewStack e apenas alternando a tela vísivel no mesmo), a outra questão a verificar é o tamanho dos arquivos transferidos. O gráfico cima ilustra bem a diferença: enquanto o ViewStack tem um custo inicial muito grande (afinal, é feito o download de tudo), o StackedModules (e isso é inerente ao funcionamento do Modules, tal como no SWFLoader) faz o download à medida que é necessário, e isso se torna ainda mais benéfico ao considerarmos que nem sempre um usuário irá acessar todos os módulos, o que tornaria o tráfego com o o Modules menor que o ViewStack. Para esse teste, os módulos foram compilados com dynamic linking, reduzindo o tamanho do SWF.

O projeto de prova de conceito está disponível para download: StackedModules.zip. O componente

1
ModuleLoaderWithProgress

incluído apresenta uma barra de carregamento (download) do módulo, mas pode ser substituído com a sua própria implementação do ModuleLoader. Importante: utilize o build.xml incluso para compilar (permitindo o dynamic linking), e não o Flex Builder diretamente. O consumo de memória foi aferido pelo

1
flash.system.System.totalMemory

.

O conceito de Stacked Modules é uma boa solução para o gerenciamento de memória e tráfego em grandes aplicativos, mas não deve ser considerada única solução caso esses quesitos sejam vitais em seu projeto.


28 comentários

  1. Fernando em 23.jan.07 às 10:12 pm

    Ótimo artigo! A genialidade de sua solução está na simplicidade e na criatividade.

  2. Leonardo França em 24.jan.07 às 12:20 am

    Parabens pelo artigo Fabio, estou com um projeto pra uma intranet e esse artigo com certeza será muito util. :)

    ate mais
    Leonardo França

  3. mindu em 19.mar.07 às 1:46 pm

    Muito interessante essa abordagem Fabio, estava procurando algo assim e o seu post/exemplo caiu como uma luva. Parabéns !
    Só não entendi uma coisa, o que vc quis dizer com compilar usando ‘dynamic linking’ ?
    Nos testes que eu fiz aqui, compilei normalmente usando o ‘mxmlc.exe’ e funcionou também, vc vê algum problema ? Tem como configurar o flex builder para compilar e gerar esses arquivos separados ao invés de usar o prompt ?
    Reparei que os arquivox mxml, deve ser do tipo ‘Module’, se fosse do tipo ‘Application’ funcionaria ? qual a diferença ?
    valeu Fábio.
    []‘s
    mindu

  4. Fabio Terracini em 19.mar.07 às 9:49 pm

    Mindu,

    Dynamic linking é um recurso para compilar o arquivo SWF com o mínimo de dependências possíveis, considerando que as demais dependências estarão presentes no arquivo que o carregou.

    Assim, o seu Aplicativo.mxml já inclui uma série de componentes (por exemplo Panel, Label, TextInput, etc) que também serão utilizados por seu Modulo.mxml. Assim o Modulo.mxml, ao ser compilado, “externaliza” a dependência dessas classes para seu outro swf. O objetivo maior é otimizar e reduzir o tamanho dos arquivos.

    Eles poderiam ser Applications se fossem utilizado em conjunto com o SWFLoader. O ModuleLoader é utilizado para carregar Modules, como no arquivo que disponibilizei. Teoricamente o efeito é o mesmo, mas o Modules é mais flexível para esse propósito específico de módulos de aplicativos.

    []s!

  5. adriana em 6.abr.07 às 11:15 am

    manual da memoria frex halloem

  6. Rodrigo Pereira Fraga em 12.abr.07 às 1:28 am

    Bacana o artigo,
    Será muito útil para aplicações posteriores e revisar algumas já feitas!
    Meus Parabéns

  7. Thiago em 22.mai.07 às 2:45 am

    Fabio muito interessante sua matéria sobre o consumo de memoria Parabéns .
    Estou com uma duvida , seguinte fiz um modulo que implementa componentes que eu criei , na tag do modulo fica assim :

    quando executo o mxmlc o compilador diz : Type was not found or was not a compile-time constant : COMBOC, eu vi no seu exemplo no aquivo build.mlx que tem parametros para o compilador , vc poderia me ajudar nesse problema ? desde já agredeço sua Atenção

  8. Charilaos em 9.jul.07 às 5:30 am

    Cool.

  9. Kleanthe em 9.jul.07 às 2:48 pm

    Cool.

  10. Iannis em 9.jul.07 às 6:02 pm

    Cool…

  11. Nickolas em 10.jul.07 às 12:37 am

    Cool.

  12. Vardis em 10.jul.07 às 2:58 am

    Sorry :(

  13. Constantine em 12.jul.07 às 11:46 am

    Cool!

  14. Aineias em 14.jul.07 às 11:57 am

    Interesting…

  15. Renato em 27.jul.07 às 12:37 pm

    Fábio, artigo muito interessante, com propriedade, foi muito útil para mim, parabéns e muito obrigado era exatamente o que eu estava procurando saber.

  16. Leandro Goulart em 13.ago.07 às 1:57 pm

    Esse artigo realmente me ajudou muito. Muito obrigado mesmo. Continuem evoluindo.

  17. Vanderlei em 23.ago.07 às 4:08 pm

    Após apreciar seu bom conhecimento, gostaria de aproveitar este espaço, para pedir um auxílio. Tenho um arquivo .fla, que ficou muito pesado, com 7,21 mb (megabites), e não conseguí mais abrí-lo de maneira alguma. Já aumentei a memória virtual, dentre várias outras tentativas. Há alguma meneita de conseguir abrir novamente o referido arquivo?

    Abraços.

  18. Vanderlei em 23.ago.07 às 4:12 pm

    REPETIÇÃO DA MENSAGEM ANTERIOR, COM ENDEREÇO DE E-MAIL PARA CONTATO

    Após apreciar seu bom conhecimento, gostaria de aproveitar este espaço, para pedir um auxílio. Tenho um arquivo .fla, que ficou muito pesado, com 7,21 mb (megabites), e não conseguí mais abrí-lo de maneira alguma. Já aumentei a memória virtual, dentre várias outras tentativas. Há alguma meneita de conseguir abrir novamente o referido arquivo?
    Se souber, por favor, entre em contato: vanrafa2@yahoo.com.br

    Abraços.

  19. Giancarlo em 28.set.07 às 1:44 pm

    Excelente Fábio! Quem dera todos os artigos que a gente encontra por ai fossem completos como o seu!

  20. Thiago em 30.out.07 às 7:48 pm

    Ótimo exemplo!!!

    Porém, creio ter encontrado algo desfavorável no uso de módulos.
    Gostaria de pedir a ajuda dos colegas para as 2 seguintes questões.

    Primeira questão.
    Vamos imaginar que estamos usando esse mesmo exemplo com gráficos,
    porém,
    a melhor prática seria que as “telas dos gráficos” fossem componentes “caixa-preta”, ou seja, que fizessem apenas a função de exibir valores, sem questionar a origem deles.

    Num exemplo sem módulos, poderiamos fazer isso de forma simples,
    usando uma “[Bindable] public var myModules:ArrayCollection=null;”
    e deixarmos que o componente-pai cuidasse de preenchê-lo.

    Porém, eu nunca encontrei uma forma de fazê-lo.
    Algum dos colegas poderia me ajudar nesse ponto?

    Segunda questão.
    Vamos analisar uma estratégia simples de programar(sem módulos),

    o Código funciona bem, vamos separar em componentes agora….

    (espero não ter ido rápido demais…)

    o que quero dizer é,
    Como podemos levantar eventos entre o MX:MODULE e MX:MODULELOADER

  21. Thiago em 30.out.07 às 7:50 pm

    Ótimo exemplo!!!

    Porém, creio ter encontrado algo desfavorável no uso de módulos.
    Gostaria de pedir a ajuda dos colegas para as 2 seguintes questões.

    Primeira questão.
    Vamos imaginar que estamos usando esse mesmo exemplo com gráficos,
    porém,
    a melhor prática seria que as “telas dos gráficos” fossem componentes “caixa-preta”, ou seja, que fizessem apenas a função de exibir valores, sem questionar a origem deles.

    Num exemplo sem módulos, poderiamos fazer isso de forma simples,
    usando uma “[Bindable] public var myModules:ArrayCollection=null;”
    e deixarmos que o componente-pai cuidasse de preenchê-lo.

    Porém, eu nunca encontrei uma forma de fazê-lo.
    Algum dos colegas poderia me ajudar nesse ponto?

    Segunda questão.
    Vamos analisar uma estratégia simples de programar(sem módulos),
    (mx:Application)
    (mx:Script)
    (![CDATA[
    [Bindable] private var s:String=”texto”;
    ]])
    (/mx:Script)
    (mx:VBox)
    (mx:Label id=”label1″ text={s}/)
    (/mx:VBox)
    (mx:HBox)
    (mx:Button id=”bt1″ click=”texto=’modifiquei o texto’”/)
    (/mx:HBox)
    (/mx:Application)

    o Código funciona bem, vamos separar em componentes agora….
    (mx:Application)
    (mx:Script)
    (![CDATA[
    [Bindable] private var s:String=”texto”;
    ]])
    (/mx:Script)
    (local:MeuVBox texto=”{s}”/)
    (local:MeuHBox quandoClicou=”texto=(event as MeuEvento).s”)

    (/mx:Application)

    (espero não ter ido rápido demais…)

    o que quero dizer é,
    Como podemos levantar eventos entre o MX:MODULE e MX:MODULELOADER

  22. Allysson Makens em 4.fev.08 às 5:50 pm

    Estou com esta mesma dúvida:
    “Fabio muito interessante sua matéria sobre o consumo de memoria Parabéns .
    Estou com uma duvida , seguinte fiz um modulo que implementa componentes que eu criei , na tag do modulo fica assim :

    quando executo o mxmlc o compilador diz : Type was not found or was not a compile-time constant : COMBOC, eu vi no seu exemplo no aquivo build.mlx que tem parametros para o compilador , vc poderia me ajudar nesse problema ? desde já agredeço sua Atenção”

  23. lol em 6.fev.08 às 7:23 pm

    winter olympics of 1972

  24. Alberto em 14.abr.08 às 4:32 pm

    Olá Fabio,
    Muito interessante o artigo. Tanto que adotei para um sistema que estou fazendo. Mesmo que o Flex 3 agora me possibilite chamar o garbage.
    Mas a dúvida é a seguinte:
    Antes eu usava o onCreationComplete para executar algo que eu gostaria que a aplicação executasse sempre na primeira vez que o módulo era acessado.
    Como vc faz isso agora, ele só exeuta a primeira vez, se eu “fechar” (no meu caso posiciono o stack no item 0) e abrir, ele não vai mais chamar a função.
    Existe algum outro evento? show, activate, etc..

    Obrigado.

  25. Maicon em 20.ago.08 às 8:59 pm

    Estou aprendendo Flex a pouco tempo (1 semana) fiz uma pequena funcao p acompanhar o uso da memoria, nao sei se pode ser util para alguem, mas p mim esta sendo, pois posso acompanhar o comportamento da memoria, comforme vou navegando no projeto, nao sei se é a forma certa, qq coisa falem…

    Notei q no Explorer o flex ocupa muito menos memoria, inicia com 5M e no FF o mesmo projeto inicia com 18M, sendo q o explorer esta com a versao 9.0.124 do player do flash e no FF a 9.0.115, entao esta diferenca pode ser (provavenmente) da versao do player e nao do navegador…

    Colocar este campo de texto no projeto:

    Colocar esta funcao no arquivo .as :
    public function atualizaMem():void
    {
    var k:int = System.totalMemory / 1024;
    var m:int = k / 1024;
    mostraMemoria.text = String(k)+” Kb / ” + String(m)+” Mb”;
    }

Trackbacks

  1. Leonardo França » Gerenciando memória e modulos no Flex 2.0.1
  2. Trabalhando com módulos e componentes no Flex « ADS - Arte De Ser
  3. Modules - redeRIA | Agregador de noticias, artigos, tutoriais Flex, Flash, JavaFX, AJAX e Rich internet applications em geral!

Deixe Seu Comentário