2008-10-10 11 views
18

¿Es posible forzar programáticamente una ejecución completa de recolección de elementos no utilizados en ActionScript 3.0?Forzar recolección de basura en AS3?

Digamos que he creado varios Objetos de visualización con eventListeners y que algunos de los OD han sido eliminados, algunos de los EventListeners se han activado y eliminado, etc. ... ¿Hay alguna manera de forzar la recolección de basura para ejecutar y recoge todo lo que está disponible para ser recolectado?

Respuesta

25

Sí, es posible, pero en general es una mala idea. El GC debería tener una mejor idea de cuándo es un buen momento para correr de lo que debería, y excepto en un caso muy específico, como que acaba de usar 500MB de memoria y necesita recuperarlo lo antes posible, no debe llamar al GC tú mismo.

En Flash 10, hay un método System.gc() que puede llamar (pero no lo haga, consulte más arriba): recuerde que System.gc() solo funciona en la versión de depuración de Flash player 10+.

En Flash 9, existe una forma no admitida de forzarlo a través de un comando LocalConnection extraño, pero es posible que no funcione en todas las versiones. Ver this post por Grant Skinner.

+7

Esta es una gran respuesta, pero se pierde un punto muy importante. ¡Solo funciona en los depuradores de todos modos! System.gc(): solo para la versión del depurador de Flash Player y las aplicaciones de AIR. En una aplicación de AIR, el método System.gc() solo está habilitado en el contenido que se ejecuta en AIR Debug Launcher (ADL) o, en una aplicación instalada, en contenido en el entorno limitado de seguridad de la aplicación. [http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/System.html#gc()] –

+1

No lo sabía. – Glycerine

+5

En Flash 11 hay un 'Sistema.método pauseForGCIfCollectionImminent() 'puede llamar. Se necesita una discusión para que pueda darle al CG una idea de cuán inminente debe ser una colección para que la pausa suceda. Para más detalles/enlaces, vea mi respuesta a continuación. – pnkfelix

8

Para todas las versiones actualmente publicadas, System.gc() solo funciona en la versión de depuración del reproductor Flash y ADL (el entorno de depuración para las aplicaciones de AIR). Flash Player 10 beta actualmente funciona en todos los sabores.

Estoy de acuerdo con Davr, es una mala idea. El tiempo de ejecución generalmente tendrá una mejor idea que tú.

Además, los detalles de cómo funciona el recolector de basura es un detalle de implementación sujeto a cambios entre las versiones de Flash Player. Entonces, lo que funciona bien hoy no tiene garantía de funcionar bien en el futuro.

+0

Hay un caso específico, tengo una clase DataCache, la forma en que funciona es que mantiene el objeto resultante que envía eventos actualizados al actualizar/recibir datos. La forma en que se limpia la caché es que limpie todos los resultados y envíe el evento que causa que los oyentes restantes vuelvan a solicitar sus datos. Si no puedo obligar a todos los oyentes que todavía cuelgan esperando a que se limpie GC inmediatamente antes de enviar el evento de actualización, los oyentes que cuelgan volverán a solicitar datos. – FredV

3

Como han dicho otros: no intente GC manualmente, hay hacks pero no es seguro.

Debe intentar reciclar objetos cuando pueda; ahorrará mucha memoria.

Esto se puede aplicar, por ejemplo, a BitmapDatas (borrar y reutilizar), partículas (eliminar de la pantalla y reutilizar).

3

Tengo un comentario sobre los que dicen que nunca debe hacer GC manualmente. Estoy acostumbrado a la administración manual de memoria en C++ y prefiero compartir mucho sobre GC, pero de todos modos.

Existe un caso específico en el que no puedo encontrar otra solución que no sea un GC. Considere: Tengo una clase DataCache, la forma en que funciona es que mantiene los objetos de resultados para ciertas llamadas a métodos que envían eventos actualizados al actualizar/recibir datos. La forma en que se actualiza el caché es simplemente limpiar todos los resultados y enviar el evento que causa que los oyentes restantes vuelvan a solicitar sus datos y los oyentes que salieron del alcance no deben volver a realizar la solicitud, lo que elimina los resultados innecesarios. Pero, al parecer, si no puedo obligar a todos los oyentes que todavía cuelgan esperando a que el GC se limpie inmediatamente antes de enviar el evento "preguntar de nuevo a los datos", los oyentes que cuelgan solicitarán datos innecesariamente. Como no puedo eliminar EventListener porque AS3 no tiene destructores, no veo otra solución fácil que forzar un GC para asegurarme de que ya no haya escuchas colgantes.

(Edit) en la parte superior de la que no puedo usar removeEventListener de todos modos por la unión que eran configuración en mxml, por ejemplo (usando mi clase DataCacher costumbre que maneja remoteobj)

<mx:DataGrid id="mygrid" dataProvider="{DataCacher.instance().result('method').data}" ... /> 

Cuando la ventana emergente que contiene esta cuadrícula de datos está cerrado, esperarías que las ataduras se destruyan. Aparentemente ellos viven y siguen. Hmm, no debería doblar destruir todas las vinculaciones (es decir, eventlisteners) de un objeto cuando está siendo marcado para GC porque se borró la última referencia. Eso solucionaría un poco el problema para mí.

Al menos es por eso que creo, todavía soy un principiante en Flex por lo que cualquier idea sería apreciada.

0

Si tiene que hacerlo, puede ser útil llamar al colector gargabe ... por lo tanto, debe tener cuidado de cómo y cuándo hacerlo, pero no hay duda de que hay momentos en que es necesario.

por ejemplo, si tiene una aplicación que es modular, cuando cambie de una vista a otra, todos los objetos eliminados podrían representar una gran cantidad de memoria que debería estar disponible lo más rápido posible, solo necesita tener control de las variables y referencias que está desechando.

0

reciclaje realmente no ayuda. Usé un cargador que cargó repetidamente el mismo jpg cada 500 ms. el administrador de tareas aún informó un aumento continuo de la memoria.

solución probada y comprobada aquí.

http://simplistika.com/as3-garbage-collection/

3
try { 
    new LocalConnection().connect('foo'); 
    new LocalConnection().connect('foo'); 
} catch (e:*){ 
    trace("Forcing Garbage Collection :"+e.toString()); 
} 
+0

¿Puede explicar cuál es el vínculo con el GC y por qué esto lo forzaría? – duTr

14

Hay una nueva API para contar la GC que podría ser un "relativamente buen momento" para recoger.

Consulte los documentos de la API de Adobe para System.pauseForGCIfCollectionImminent

Y también esta Adobe blog post desde poco después de que el método se introdujo en la versión Player 11

El método toma un argumento "inminencia"; básicamente, alimentas en un número bajo (cerca de 0.0) si realmente quieres que el recopilador se ejecute, incluso si no ha habido mucha actividad (actualmente medida por bytes asignados) desde la última colección, y alimentas un gran número (cerca de 1.0) si solo desea que se produzca la pausa de recopilación si ya estuviéramos cerca del punto en el que se realizaría una recopilación.

La motivación aquí es para situaciones en, por ejemplo, juegos en los que desea cambiar el punto en el que los GC ocurren por una pequeña cantidad, p. hacer el GC durante un cambio de nivel en el juego, en lugar de dos segundos después de que el jugador comenzó a explorar el nivel.

Un detalle muy importante: esta nueva API es compatible tanto con Release como con Debugger Flash Runtimes. Esto lo hace superior a llamar a System.gc().

Cuestiones relacionadas