¿Quieres registrarte?

Clase para manejar el Garbage Collector de Flash Player

Por: alfathenus
3 de Febrero del 2009

Como todos sabrán el Flash Player, si no lo controlamos de cerca, es un verdadero pozo sin fondo que se come la memoria de la máquina y hace que la experiencia de usuario en un sistema web (Flex/Flash) o en un sitio con alto contenido gráfico/video/3D sea un suplicio y terminemos optando por salir de la web o en el peor de los casos reiniciando el browser.

Aca les dejo una clase que maneja el Garbage Collector (GC) del Flash player. Esta clase provee diferentes métodos, veamos:

Eliminar loaders con unloadAndStop si se puede y ejecutando el GC si se lo indica

Código :

 loader = new Loader();
.
.
Cleanner.unload(loader, true);


Ejecución del GC

Código :

Cleanner.gc();


Ejecución automática del GC (si supera x cantidad de memoria usada) cada x cantidad de segundos (permite configuraciones varias)

Código :

Cleanner.startGCController()


Esta clase ejecuta el codigo correspondiente dependiendo del FP que se tenga.

Por otro lado esta clase solo intenta mejorar la liberación de memoria para elementos cargados dinámicamente y la ejecución automática del GC, con herramientas que nos provee AS3.0. Otros problemas de sobrecarga de memoria corresponden a un control propio del programador, tales como:

1. No tener referencias cruzadas
2. Eliminar todas las refencias, listeners, sonidos, videos, eventos, efectos, etc de los elementos q se van a elimiar
3. Usar referencias débiles
4. Hacer un buen testing de performance.

Tal vez esto sea bueno para combinarlo con un visor del framerate, ya que a veces suele ir de la mano la caida del framerate con el gran uso de memoria..

Igualmente a esta clase aun le faltan un par de cositas, pero se puede utilizar tranquilamente...

Bueno, aca les dejo la clase

Código :

/**
 * 
 * Copyright (c) 2008 Andrés Lozada Mosto, All Rights Reserved.
 * 
 * Contact alfathenus@gmail.com
 * See www.3wstudio.com.ar
 *  
 * Permission is hereby granted, free of charge, to any person obtaining a copy of 
 * this software and associated documentation files (the "Software"), to deal in 
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all 
 * copies or substantial portions of the Software.
 * 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 * 
 */
package com.kcc.tempos.utils.loaders
{
   import flash.display.Loader;
   import flash.errors.IllegalOperationError;
   import flash.net.LocalConnection;
   import flash.system.System;
   import flash.utils.clearInterval;
   import flash.utils.setInterval;
   
   /**
    * 
    * Provide an API to manage dynamic memory of Flash Player.
    * 
    * <p>The <code>Cleaner</code> class contains the following static variables and functions </p> 
    * <pre>
    *    <b>Variables</b>
    *    static public var warningMemory:int;
    *    static public var abortMemory:int;
    *    static public var funcCrash:Function;
    *    static public var timeToCheckMemory:int;
    *    <b>Functions</b>
    *    static public function unload(loader:Loader, gc:Boolean = false):void;
    *    static function gc():void;
    *    static public function startGCController():void;
    *    static public function endGCController():void;
    * </pre>
    * 
    * 
    * @playerversion Flash 9
    * @langversion 3.0
    * 
    * 
    * Sites to help me:
    * (1) http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/
    * (2) http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html
    * 
    * Next steps
    * # Test perfom
    * # Full functionaly testing over diferents situations and environments
    * # Add Air total Support
    * # English documentation
    * 
    */
   
   public class Cleanner
   {
      //-----------------------
      // Variables
      //-----------------------
      /**
       * Memoria para ejecutarse el GC
       */
      static public var warningMemory:int = 1000*1000*500;
      /**
       * Memoria para el crash
       */
      static public var abortMemory:int = 1000*1000*625;
      /**
       * Funcion q se ejecuta al hacer crashh (sin memoria)
       */
      static public var funcCrash:Function;
      /**
       * Cada cuanto tiempo se verifica el uso de la memoria 
       * cuando se esta haciendo el trakeo
       */
      static public var timeToCheckMemory:int = 10000;
      static private var id:int; 
      //-----------------------
      // Constructor
      //-----------------------
      public function Cleanner()
      {
         throw new IllegalOperationError("ClearLoaders is static. It don't create intances"); 
      }
      
      //-----------------------
      // Public Methods
      //-----------------------
      /**
       * 
       * Elimino algo que haya cargado por Loader.
       * No siempre combiene pasar el GC luego de 
       * eliminar un modulo o swf cargado porque caería
       * la eficiencia general de la aplicación.
       * 
       * @param loader       Referencia a un Loader
       * @param gc         Indica si al descargar debe correrse el Garbage Collector
       * 
       */
      static public function unload(loader:Loader, gc:Boolean = false):void
      {
         try
         { // para FP 10 o superior
            loader.unloadAndStop()
         }
         catch (e:Error)
         {
            loader.unload();
         }
         
         if ( gc )
            Cleanner.gc();
      }
      
      /**
       * 
       * Ejecuto el Garbage Collector del Flash Player
       * para que libere la memoria
       * 
       */
      static public function gc():void
      {
         try
         { // para FP10 o superior
            System.gc();
         }
         catch
         {
            try { // versiones anteriores
               new LocalConnection().connect('foo');
               new LocalConnection().connect('foo');
            } 
            catch (e:*) 
            {
            }
         }
      }
      
      /**
       * 
       * Trackea el uso de la memoria y la va liberando
       * de forma automatica
       * 
       */
      static public function startGCController():void
      {
         if (Cleanner.id == null || Cleanner.id == undefined)
         {
            Cleanner.checkMemoryUsage();
            Cleanner.id = setInterval(checkMemoryUsage, Cleanner.timeToCheckMemory);
         }
      }
      
      /**
       * 
       * Termino el trackeo de la memoria
       * 
       */
      static public function endGCController():void
      {
         clearInterval(Cleanner.id);
         Cleanner.id = undefined;
      }
      
      //-----------------------
      // Private Methods
      //-----------------------
      static private function checkMemoryUsage() {
         if (System.totalMemory > Cleanner.warningMemory) {
            Cleanner.gc();
          } else if (System.totalMemory > Cleanner.abortMemory) {
            //crashhhhh 
            if ( Cleanner.funcCrash != null )
               Cleanner.funcCrash();
          }
      }
   }
}


Bueno, espero q les sirva y les sea de utilidad.... y ojalá entre todos la podamos ir mejorando y agregandole funcionalidades interesantes.

Saludos!!

Enviar a twitter Enviar a facebook


También te interesa


Etiquetas actionscript_3 flashplayer

Comentarios | Enviar un comentario
Se ve bien esa clase. Buen trabajo (y)
Por: Zguillez
Genial clase! (y)

Usualmente en el desarrollo de pequeñas aplicaciones o webs no notamos el consumo real de nuestro SWF, pero cuando nos toca desarrollar algo más grande o desarrollar juegos donde intervienen muchos eventos, variables, etc; el consumo de la memoria se ve afectado y en muchos lados decían que el Garbage Collector se disparaba cuando él quería y esto llevaba a que la memoria aumente.

Pero gracias al Flash Player 10 y más aun a la solución que das con esa clase, el mundo podrá ser salvado. ^^

Gracias por compartirlo (y) .
Por: Otaku RzO

Código :

System.gc();


Interesante... Muchas gracias!
Por: Juanlu_001
muy bueno, yo lo hacia liberando la memoria después del uso ^^

De hecho q la clase q tienes es útil, podemos ir haciéndolo multiusos ;)

Felicitaciones, buen aporte
Por: eldervaz

Código :

try 
         { // para FP 10 o superior 
            loader.unloadAndDestroy() 
         } 
         catch (e:Error) 
         { 
            loader.unload(); 
         } 


loader..unloadAndDestroy() ?? que no es .unloadAndStop() ?? :?

no tengo ese metodo unloadAndDestroy, a mi me sale el unloadAndStop y tengo el SDK 3.2
Por: phoxer
Phoxer!! Gracias por corregir el error je....

Bueno gente... cambien esa linea de codigo.... o bien q algun moderador edite el post asi queda la clase bien escrita

Gracias phoxer! (raro q nadie se dio cuenta antes no? je)
Por: alfathenus
Me sucede otro problema el usar el unloadAndStop().. no se si a alguien le paso.

yo utilizo FlashRemoting para conectarme con MySql, generalmente yo hago la coneccion a la base para luego trabajarla, desde la clase principal, osea que siempre desde los módulos me conecto con la clase principal que tengo en "root" por asi decirlo, con esto me evito de andar configurando la clase de coneccion en toooodos lados..

bien el problema esta que en el servidor el unloadAndStop me funciona bien, pero Localmente, ejecutado desde el Flex o el Flash, me cierra la coneccion, y eso que solamente borro un clip o un modulo que no tiene incluso una coneccion relacionada, porque me cierra la coneccion que nada tiene que ver con el Loader??

Salida :

NetConnection.Connect.Closed
Error #2044: IOErrorEvent no controlado: text=Error #2036: No se completó la carga

Por: phoxer
[quote=""Otaku RzO]decían que el Garbage Collector se disparaba cuando él quería y esto llevaba a que la memoria aumente.[/quote]

No, no se lanza cuando quiere, se lanza cuando la memoria utilizada sobrepasa el limite de memoria que tiene asignado el flash player... el tema es q si ese limite es alto, por ejemplo tenemos 5 juegos en flash abiertos, por lo tanto el FP tiene asigndo 100 mb de memoria, y luego cerramos 4 juegos la memoria ocupada por los juegos q cerramos no se libera... y ese no es un tema del GC sino del uso de memoria del FP q no esta del todo optimizada.

La idea de q el GC se ejecute unicamente cuando ya no hay memoria es cuestion de rendimietno, si el GC se ejecutara tanto como lo hace la maquina virtual de java el rendimiento bajaria ya q es un proceso costoso...

Por lo tanto, tengan cuidado en lanzar muy seguido el System.gc() porq en vez de mejorar el rendimiento lo van a tirar abajo....


Saludos!
Por: alfathenus
Phoxer, creo q es un tema del unlaodAndStop... q para el modulo q estas descargando cierra tambien cualquier NetConnection q utilice..... talvez tengas instanciada en el swf q estas borrando alguna referencia al remoting.... si es asi es posible q flash recorra las varaibles y cierre cualqueir coneccion extarna q haya en cualqueir varaible...

Proba, si es q tenes referencias a la variable del remoting del root en el swf... en eliminar es referencia primero y luego borrar el swf.... Q se yo... es algo q se me ocurrio recien...


Saludos!
Por: alfathenus

alfathenus :

Gracias phoxer! (raro q nadie se dio cuenta antes no? je)


No es un error señor, es que suena mejor Destroy que Stop jajaa

También es que yo soy un poco obsesionado con el echo de borrar referencias.. Quiero aprender a usarlalas mas que nada porque quiero orientarme de a poco a hacer mejores sistemas y videojuegos :lol:

esta clase que hiciste esta muy buena Gracias a vos por aportarla. :)
Por: phoxer

alfathenus :

Phoxer, creo q es un tema del unlaodAndStop... q para el modulo q estas descargando cierra tambien cualquier NetConnection q utilice.....


si eso es lo que esta haciendo, pero lo raro es que me lo hace solamente cuando lo ejecuto en local, desde el Flash o del Flex y no sobre un Servidor, sobre un servidor (desde el explorador) no me cierra las conecciones o no esta andando el UnloadAndStop jajaja.. ya voy a hacer algunos testings para ver que es lo que pasa... Gracias
Por: phoxer

alfathenus :

Bueno gente... cambien esa linea de codigo.... o bien q algun moderador edite el post asi queda la clase bien escrita

Done!
Por: Zguillez

Zguillez :

alfathenus :

Bueno gente... cambien esa linea de codigo.... o bien q algun moderador edite el post asi queda la clase bien escrita

Done!


Gracias!
Por: alfathenus
Pues... el hack del LocalConnection jode el player en ciertas circunstancias. Yo no lo usaria si fuera ustedes.
Por: fernando
por cierto, si checan la documentación de System.gc() dice:

"For the Flash Player debugger version and AIR applications only."
Por: fernando
Rayos, fernando tiene razón... ¿En ese caso tu clase no funciona?
Por: Juanlu_001

alfathenus :

Otaku RzO :

decían que el Garbage Collector se disparaba cuando él quería y esto llevaba a que la memoria aumente.


No, no se lanza cuando quiere, se lanza cuando la memoria utilizada sobrepasa el limite de memoria que tiene asignado el flash player... el tema es q si ese limite es alto, por ejemplo tenemos 5 juegos en flash abiertos, por lo tanto el FP tiene asigndo 100 mb de memoria, y luego cerramos 4 juegos la memoria ocupada por los juegos q cerramos no se libera... y ese no es un tema del GC sino del uso de memoria del FP q no esta del todo optimizada.

La idea de q el GC se ejecute unicamente cuando ya no hay memoria es cuestion de rendimietno, si el GC se ejecutara tanto como lo hace la maquina virtual de java el rendimiento bajaria ya q es un proceso costoso...

Por lo tanto, tengan cuidado en lanzar muy seguido el System.gc() porq en vez de mejorar el rendimiento lo van a tirar abajo....


Saludos!
Gracias por la aclaración.

fernando-blog :

por cierto, si checan la documentación de System.gc() dice:

"For the Flash Player debugger version and AIR applications only."
es cierto. :wtf:
En verdad necesitamos un artículo detallado sobre el Garbage Collector.
Por: Otaku RzO
tengo un flash para ver fotos, que en cierto momento llega a pesar 1.2 giga de ram, y usando esto: System.gc(); no me funciona :S
Por: lucasmoyano
Deja un comentario
IMPORTANTE

Recuerda ser respetuoso, no insultes a otras personas, ni uses palabrotas, hay una persona al otro lado de la pantalla.

Habla bien, NO ESCRIBAS EN MAYUSCULA TODO, no escribas como en un SMS, evita cosas como "ke", "x q" y demás abreviaciones.

Aquí funcionan las etiquetas de los foros, puedes usar [b] para negrita, [img] para las imágenes, [url] para los enlaces, etc.

Si tienes preguntas técnicas, envíalas mejor al foro.