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 [email protected] * 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!!
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.
Por Zguillez el 06 de Febrero de 2009
Por Otaku RzO el 06 de Febrero de 2009
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 .
Por Juanlu_001 el 06 de Febrero de 2009
Código :
Interesante... Muchas gracias!
Por eldervaz el 06 de Febrero de 2009
De hecho q la clase q tienes es útil, podemos ir haciéndolo multiusos
Felicitaciones, buen aporte
Por phoxer el 06 de Febrero de 2009
Código :
loader..unloadAndDestroy() ?? que no es .unloadAndStop() ??
no tengo ese metodo unloadAndDestroy, a mi me sale el unloadAndStop y tengo el SDK 3.2
Por alfathenus el 06 de Febrero de 2009
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 phoxer el 06 de Febrero de 2009
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 :
Error #2044: IOErrorEvent no controlado: text=Error #2036: No se completó la carga
Por alfathenus el 06 de Febrero de 2009
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 el 06 de Febrero de 2009
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 phoxer el 06 de Febrero de 2009
alfathenus :
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
esta clase que hiciste esta muy buena Gracias a vos por aportarla.
Por phoxer el 06 de Febrero de 2009
alfathenus :
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 Zguillez el 06 de Febrero de 2009
alfathenus :
Done!
Por alfathenus el 06 de Febrero de 2009
Zguillez :
alfathenus :
Done!
Gracias!
Por fernando el 07 de Febrero de 2009
Por fernando el 07 de Febrero de 2009
"For the Flash Player debugger version and AIR applications only."
Por Juanlu_001 el 07 de Febrero de 2009
Por Otaku RzO el 09 de Febrero de 2009
alfathenus :
Otaku RzO :
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!
fernando-blog :
"For the Flash Player debugger version and AIR applications only."
En verdad necesitamos un artículo detallado sobre el Garbage Collector.
Por lucasmoyano el 04 de Agosto de 2009
Por driegon el 19 de Septiembre de 2010
Código :
el primer "catch" no debiera tener un parametro también?:
Código :
Por nohien el 16 de Junio de 2011