Optimisation code AS3 pour Garbage Collector

Résolu
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011 - 23 oct. 2009 à 09:50
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012 - 14 nov. 2009 à 17:13
Hello,

J'aurai juste quelques question afin d'optimiser mon code AS3 pour le passage du Garbage Collector.

1/ Imaginons une classe :
package 
{
     import flash.events.*;
     public MyClass extends Movieclip()
     {
          private var myClip:Sprite;
          public function MyClass()
          {
               myClip = new Sprite();
               addChild(myClip);
               myClip.addEventListener(MouseEvent.CLICK, clicking);
          }
     }
}


Puis une instanciation

import MyClass;
var o:MyClass = new MyClass();
addChild(o);


Si je fais un removeChild(o) puis un o = null, dois-je au préalable appeler une fonction dans ma classe MyClass qui fera :

removeChild(myClip)
removeEventListener(MouseEvent.CLICK, clicking)
myClip = null


???

Ou le fait de faire un removeChild() de l'instance de mon objet suffit ?

Merci

-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
A voir également:

42 réponses

gogogadjet Messages postés 28 Date d'inscription mardi 20 septembre 2005 Statut Membre Dernière intervention 10 juillet 2010
4 nov. 2009 à 21:39
bande de tueur !! je n'arrive pas à me désabonner de ce forum, je recoit un mail toutes les 30 sec .... vous n'avez pas un tchat ....
0
pegase31 Messages postés 6138 Date d'inscription dimanche 21 décembre 2003 Statut Modérateur Dernière intervention 4 septembre 2013 12
4 nov. 2009 à 22:43
@gogogadjet : il suffit de te désabonner de ce sujet dans ton compte tout simplement ...

@orange73 : un objet qui ne peut pas être enlevé par le garbage collector retiens les autres objets aucuel il est associé.

Peg'
0
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
4 nov. 2009 à 23:00
Peg,

Pour que ce soit bien clair dans nos esprits à tous, pourrais-tu poster un code approchant, mais qui ne serait pas enlevé par le GC ?

Parce que j'ai quand même l'impression de manquer quelque chose, maintenant...

Merci !

TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
pegase31 Messages postés 6138 Date d'inscription dimanche 21 décembre 2003 Statut Modérateur Dernière intervention 4 septembre 2013 12
4 nov. 2009 à 23:25
Pas trop le temps pour un code ce soir, mais les choses sont simples :

Un objet qui n'a aucun écouteur actif, qui n'appartiens à aucune liste d'affichage (sur la scène, ou pas), qui n'est pas instancié dans un autre objet et qui ne contiens aucun objet ayant les 4 attributs que je viens de définir, sera effacé automatiquement, quand le garbage collector passera (non contrôlé).

Je ne vois pas où est le problème ...

Peg'
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
5 nov. 2009 à 06:39
Ahh, si la gestion des fuites de mémoires et la désactivation des objets d'affichages était aussi simple que cette regle...
Le problème, c'est qu'en pratique, il n'y a pas de méthode donnée pour effectuer une bonne désactivation.
Il faut faire attention à chaque référence, toujours savoir ce qui est chargé ou pas à tout moment, se méfier des références circulaires ou externes (ma spécialité, ca... pas bien !)...
Sur une "grosse" application, cela peut prendre un temps énorme.
Alors on essaye de trouver une recette qui aiderait tout le monde à bien faire sa check list et éviter les ennuis... (comme moi sur mon accordéon, par exemple.)



TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
5 nov. 2009 à 09:43
ouai c'est clair.

Donc en fait le removeChild de myClip dans la classe est obligatoire si j'ai bien compris car sinon il fait parti de la displayList de la classe et donc si pas "removeChilder", myClip ne peut pas etre ramasser par le GC et donc l'instance de la classe sur la scene non plus car elle contient myClip qui ne peut pas être ramassé.

C'est bien cela Peg' ?


-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
pegase31 Messages postés 6138 Date d'inscription dimanche 21 décembre 2003 Statut Modérateur Dernière intervention 4 septembre 2013 12
5 nov. 2009 à 15:19
oui

Peg'
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
5 nov. 2009 à 19:50
Le fait de mettre a null les instances est t'il obligatoire ?



-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
5 nov. 2009 à 19:55
Ben après quelques tests sur le profiler de flex, il semble bien que oui. J'ai dit des aneries plus haut, désolé, vraiment.

Je pense que je vais rester sur le sujet. C'est trop important.
Je retourne à mes tests sur le profiler...

TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
5 nov. 2009 à 20:57
Argh ! Pourtant, dans ce code,

package
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.*;

public class Testeur extends Sprite
{
private var rectangle:Shape;

public function Testeur()
{
addEventListener(Event.ADDED_TO_STAGE, active);

}

private function active (evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, active);
addEventListener(Event.REMOVED_FROM_STAGE, destruct);
rectangle = new Shape();
rectangle.graphics.beginFill(0x0055FF);
rectangle.graphics.drawRect(50,50,1200,1200);
rectangle.cacheAsBitmap = true;
addChild(rectangle);
}

private function destruct (evt:Event):void
{
removeEventListener(Event.REMOVED_FROM_STAGE, destruct);
removeChild(rectangle);

}

}
}


Le rectangle est effectivement enlevé de la mémoire si le Sprite qui contient Testeur est enlevé de la liste d'affichage, sans être obligé de faire
rectangle = null;


Je continue mes tests...

TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
6 nov. 2009 à 09:25
Cool.

Et si tu ne fais pas de removeChild(rectangle) ?

Et ce que l'instance de Testeur et virer de la memoire ? sans null ? et rectangle qui est a l'interieur ? sans null ?


-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
6 nov. 2009 à 09:35
La meilleure des manière pour optimiser votre application et supprimer les références qui empêchent le Garbage Collector de supprimer des objets de la mémoire reste encore de supprimer les eventListener et mettre ses propriétés membres à null dans une méthode qui serait appelée juste avant la destruction de l'objet.

Par exemple, vous pouvez rajouter dans votre objet une méthode destroy:

private function destroy():void{
myEventDispatcher.removeEventListener("eventName", eventHandler);
myEventDispatcher =  null;
myProperty = null;
...
}



Source : http://www.flex-tutorial.fr/2008/12/12/flex-debug-garbage-collector-as3-gestion-des-ressources/

Donc apparement pas besoin de removeChilder les instances a l'interieur de la classe mais simplement les mettre a null.

Par contre pour "myProperty = null;", si on a une vingtaine de proprietes de tout type (Number, Sprite, Shape, Class, ...), je me vois mal mettre a null ces 20 propriétés !

Donc je ne sais pas si "myProperty null;" est obligatoire. Je ne penses pas. Mais simplement pour les instances (var myClip new Sprite(); myClip = null).


-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
6 nov. 2009 à 09:41
Là aussi apparament un simple "_instance = null" suffit :
http://maohao.wordpress.com/2007/07/15/garbage-collection-in-fpas3/


-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
pegase31 Messages postés 6138 Date d'inscription dimanche 21 décembre 2003 Statut Modérateur Dernière intervention 4 septembre 2013 12
6 nov. 2009 à 09:51
un truc à savoir : un displayObjet faisant partie d'une liste d'affichage ne peut pas être "null". donc le passage à "null" fait un "remove" aussi.

Peg'
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
6 nov. 2009 à 10:27
donc le passage à "null" fait un "remove" aussi.


var myClip:Cliper = new Cliper(); // Liaison bibliotheque
addChild(myClip);

myClip = null;


myClip n'est pas "removed" !

mais myClip sera ramasser par le GC car aucune instance n'est lié, non ?


-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
6 nov. 2009 à 16:35
Et si tu ne fais pas de removeChild(rectangle) ?

Et ce que l'instance de Testeur et virer de la memoire ? sans null ? et rectangle qui est a l'interieur ? sans null ?


Je viens de faire le test sans removeChild(rectangle) dans la function destruct :

"Testeur" et le "rectangle" qu'il contient sont virés de la mémoire.



TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
6 nov. 2009 à 16:46
Alors verdict ? Quel code fonctionne ?


-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
Orange73 Messages postés 1375 Date d'inscription dimanche 28 novembre 2004 Statut Membre Dernière intervention 2 août 2011
6 nov. 2009 à 17:22
Ok cool :) merci !

Donc si on reprend mon code de base :

package 
{
     import flash.events.*;
     public MyClass extends Movieclip()
     {
          private var myClip:Sprite;
          public function MyClass()
          {
               myClip = new Sprite();
               addChild(myClip);
               myClip.addEventListener(MouseEvent.CLICK, clicking);
          }
     }
}


Sur le stage :

var _inst:MyClass = new MyClass();
addChild(_inst);


Pour un ramassage du GC, on doit :
1/ Virer l'ecouteur de myClip
2/ removeChilder "_inst" sur le stage, ce qui entraine le removeChild de myClip
3/ Par contre si myClip etait "public" et que sur le stage j'aurais creer une reference vers lui :
var objClip:Sprite = inst.myClip

je dois mettre a null "objClip".

C'est bien cela en résumé ? :)



-- Orange73 --

"L'homme n'est pas fait pour travailler, la preuve c'est que cela le fatigue" (Voltaire)
0
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
6 nov. 2009 à 17:40
Oui pour moi, à condition que myClip soit totalement inerte en interne (pas d'écouteurs, de tweens, de compteurs...

Il me reste à tester le fait que myClip puisse avoir une référence à myclass (avec this.parent) ou à la scene (this.stage) dans une variable interne. Mais je sens que comme le disait Peg, ça bloquera la libération de la mémoire.

Je dois aussi tester les références faibles vers des objets d'affichages. On est loin d'avoir épuisé le sujet.




TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
Twinspirit Messages postés 58 Date d'inscription mercredi 21 mai 2008 Statut Membre Dernière intervention 7 mai 2012
6 nov. 2009 à 18:07
Allez, encore un petit pour ce soir :

package
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.*;

public class Testeur extends Sprite
{
public var rectangle :Shape;
public function Testeur()
{
addEventListener(Event.ADDED_TO_STAGE, active);

}

private function active (evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, active);
addEventListener(Event.REMOVED_FROM_STAGE, destruct);

rectangle = new Shape();
rectangle.graphics.beginFill(0x0055FF);
rectangle.graphics.drawRect(50,50,1200,1200);
rectangle.cacheAsBitmap = true;
//ajoute le rectangle dans la liste d'affichage
addChild(rectangle);

//on passe la variable à null, 
//mais le rectangle existe toujours en mémoire, le GC ne le prends pas. 
//l'objet peut exister sans variables dans la liste d'affichage
rectangle = null;

//a partir de là, le seul moyen d'accéder au rectangle 
//pour l'éliminer et le rendre eligible au GC
//c'est d'utiliser les methodes "getChild" des displayObjectContainer 

removeChild(this.getChildAt(0));

//Le rectangle est effacé de la liste,
//La mémoire est liberée au passage du GC
}

private function destruct (evt:Event):void
{
removeEventListener(Event.REMOVED_FROM_STAGE, destruct);
}

}


TwFlash - Développeur ActionScript3 freelance.
Mon blog : Twin Flash Blog
Mon site : TwFlash
0
Rejoignez-nous