[AS3] Supprimer une instance correctement

Supprimer une instance correctement [AS3] - Flash/ActionScript - Programmation

Marsh Posté le 23-02-2010 à 14:41:49    

Bonjour,
 
Je suis en train de faire mon site full flash...
Je m'éclate plutôt bien car j'apprends plein de truc, mais je rencontre un problème !
 
En AS3, supprimer une instance d'objet s'avère être particulier avec le Garbage Collector qui gère à sa manière !
Pour le moment, pour me débarrasser d'un element, j'efface ses écouteurs, je le retire avec removeChild si il s'agit d'un élément graphique, puis je lui applique la valeur "null"...
 
Le problème, c'est que ça ne semble pas fonctionner :
Dans la galerie site, quand on zoom sur une vignette, dé-zoom, puis rezoom etc..., On se rend compte rapidement que le taux de FPS chute constamment...
Tout me laisse donc penser que Flash garde en mémoire l'instance du clip qui fait office de texture à ma vignette zoomée...
 
Mon site : http://urfman.free.fr/fhw/ilotAbai [...] v2010.html (cliquez sur le cube pour lancer la galerie)
Ne vous étonnez pas si il y a que des plan rose ou vert, et qu'une fois zoomés, on vois juste un espece de cercle qui tourne, c'est encore en construction :o
 
La portion de code dédiée à l'activation/désactivation de map :
 

Code :
  1. public function activeMap():void
  2. {
  3. interactiveMC = new vignetteSprite();
  4. interactiveMC.buildMap(mapLow.bitmap,null,null);
  5. mapInteractive = new MovieMaterial(interactiveMC);
  6. this.material = mapInteractive;
  7. }
  8.         
  9. public function desactiveMap():void
  10. {
  11. material = mapLow;
  12. interactiveMC = null;
  13. mapInteractive = null;
  14. }

Pour info, cette portion est dans ma class de vignette 3D qui hérite de la classe Plane d'Away3D.
Pour mettre dans le contexte :
mapInteractive est un MovieMaterial (pour appliquer un MovieClip/Sprite en guise de texture sur un objet 3D)
vignetteSprite est mon clip en question, sa fonction buildMap lui permet de s'auto-construire si j'ose dire...
interactiveMC est l'instance de vignetteSprite...
mapLow  est le material par defaut de ma vignette
 
Merci à tous ceux qui peuvent m'aider :)
 


---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 23-02-2010 à 14:41:49   

Reply

Marsh Posté le 23-02-2010 à 15:45:01    

Je ne pense pas que ça vienne de tes instances. Le Garbage Collector fonctionne pas trop mal. Et les displayList de AS3 ont apportées beaucoup de bonne chose pour ça.
 
Bref, je me souviens d'avoir fait des anims avec du code qui faisait des duplicateMovieClip en grande quantité (à l''époque d'AS2 donc).
Les trucs devaient tournés des mois sans s'arrêter sur des écrans dans un showroom. Et ben en soignant bien, j'avais aucune monté en charge.
 
Je pense donc que ton problème est issue de Away3D ... c'est lui qui doit garder un cache ou quelque chose. Cherche dans la doc, si il parle de cache, temp ou autre.
 
Sinon, essaie de te trouver des outils de debuggage qui puissent te dire exactement ce qui se passe dans ton anim ... surtout au niveau de la mémoire.


---------------
Jeu de simulation Boursière - Version BETA - https://www.facebook.com/wildstocks
Reply

Marsh Posté le 23-02-2010 à 15:57:18    

Je n'arrive pas à faire baisser les fps : quelle est la marche à suivre pour produire ce bug ? Ca a l'air de bien fonctionner chez moi :??:


---------------
Free Daweed - "The game might crash, but at least the trains will run on time" - Chris Roberts 2018 - Je fais ma pute pour un Dragonfly : STAR-V6VM-MD7X
Reply

Marsh Posté le 23-02-2010 à 16:24:24    

Fenston, va au 3eme niveau de ma galerie (pour ça, clique sur la 1ere vignette du 1er niveau, puis la 4eme du 2nd...)
clique sur une vignette pour zoomer dessus, puis retourne en arriere en cliquant dans le vide, puis rezoom, tu peux aussi cliquer sur les vignettes voisine une fois zoomé...
Bref, moi je commence à 16-17 fps (zoomé), et au bout d'une 10zaine de zoom/dézoom, je suis à 7 ...
 
Zed, en AS2, un simple delete suffisait... en AS3, tu dois mettre la valeur de l'objet à null, ce qui est sencé mettre l'objet dans le GC... Celui-ci ne le supprime pas forcément instantanément, mais c'est sensé être bien foutu à ce niveau...

Citation :

In AS2, when you delete an object, the player pretty much grabs it, carries it to the incinerator, shoves it in and watches to make sure it’s completely destroyed. You delete it and it’s gone.
 
On the other hand, when you delete an AS3 object, it gets put out on the sidewalk in a big green bag for later pickup. Eventually, the garbage collector will come along and take it away. Maybe in the next couple of milliseconds, maybe some time later in the week. If you look, you might still see it there, but it’s not really polite to keep staring at it.
 
I guess it’s just one of those things that at first kind of bugs you, because you know it’s sitting there, and you want it to be actually gone. But I guess after a while, you have faith that the GC really does take care of it in good time, and you start to relax.
 
I can’t claim to know much about that stuff, but apparently this is much better, more efficient, etc. Fine with me, now that I know what’s happening. Anyway, just wanted to share that in case anyone else runs into the same thing.


Je pense pas qu'il s'agisse d'Away3D, mais plutôt de moi, je ne pige pas trop ce système de GC...
Je vais essayer de ne pas instancier moi même mon Clip (dans une variable), mais le creer directement dans la propriété material de mon plan...


---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 23-02-2010 à 16:52:52    

J'ai réussis à reproduire le bug. J'ai eu du mal, mais effectivement, ça peut poser problème.
J'ignore comment résoudre ton problème de garbage collector, mais une façon de le contourner serait de preload tes galeries une fois au lancement au lieu de les charger à la volée à chaque fois.


---------------
Free Daweed - "The game might crash, but at least the trains will run on time" - Chris Roberts 2018 - Je fais ma pute pour un Dragonfly : STAR-V6VM-MD7X
Reply

Marsh Posté le 23-02-2010 à 18:56:43    

Fenston a écrit :

J'ai réussis à reproduire le bug. J'ai eu du mal, mais effectivement, ça peut poser problème.
J'ignore comment résoudre ton problème de garbage collector, mais une façon de le contourner serait de preload tes galeries une fois au lancement au lieu de les charger à la volée à chaque fois.


Euh... je ne vois pas le rapport...
Mon problème n'est pas lié au chargement d'un élément, mais d'en supprimer un pour de bon, qu'il arrête de titiller mon CPU alors qu'j'l'ai traité de null  :o

Message cité 1 fois
Message édité par abais le 23-02-2010 à 18:57:00

---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 23-02-2010 à 19:03:25    

Et t'as pas trouvé des blogs d'Indiens qui auraient trouvés une solution alternatives ou développé un code pour parer ça ?


---------------
Jeu de simulation Boursière - Version BETA - https://www.facebook.com/wildstocks
Reply

Marsh Posté le 23-02-2010 à 19:20:46    

Non, j'allais soumettre mon pb sur le forum support d'Away 3D, mais vu que ça me semblait plutôt être un problème de compréhension de l'AS3, c'était pas forcément une bonne idée... J'aimerais savoir si c'est un bug dejà, ou une erreur de ma part...


---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 23-02-2010 à 21:17:07    

abais a écrit :


Euh... je ne vois pas le rapport...
Mon problème n'est pas lié au chargement d'un élément, mais d'en supprimer un pour de bon, qu'il arrête de titiller mon CPU alors qu'j'l'ai traité de null  :o


 
J'avais mal compris ton problème. Je croyais que je soupçonnais le Garbage Collector de passer trop souvent alors que tu lui reproches de pas passer assez.  
Le Garbage Collector libère la mémoire occupée par des objets qui n'ont plus de référence. C'est ce que tu fais avec var toto = null; Mais il y a d'autres cas de figure qui amènent un objet à ne plus avoir de référence : lorsque tu crées un objet en local dans une fonction sans garder de référence dessus en global.
Tu penses que le GC ne libère pas la mémoire à chaque fois que tu crées un objet et que tu lui supprimes sa référence. La solution, pour valider ta théorie, et est préloader des objets une fois en global au lancement de ton application, en les stockant par exemple dans un array. Par la suite, tu n'auras qu'à utiliser ces objets là plutôt que d'en créer de nouveaux à chaque fois que tu passes par la méthodes. Ainsi, t'es sur de garder une référence sur ton objet et de ne pas solliciter le garbage collector. Si ton application continue de ramer au bout d'un certain moment, c'est que tu as tort.
 
Perso, je pense pas que ça vienne de là. Ce genre de problème en général sont provoqué par deux choses :  
 - Les fuites mémoires  
 - Les timers qui bouclent sur eux même.
Utilises-tu des timers ? Si oui, es-tu sur et certain qu'ils ne continuent pas à agir malgré un cleartimeout ? J'ai déjà eu de mauvaises surprises à cause de ça... [:spamafote]


---------------
Free Daweed - "The game might crash, but at least the trains will run on time" - Chris Roberts 2018 - Je fais ma pute pour un Dragonfly : STAR-V6VM-MD7X
Reply

Marsh Posté le 23-02-2010 à 23:18:09    

Je n'utilise pas de timer...
Ce que tu dis est valable si c'est la création en soit de mes instances qui est lourde, mais ce n'est pas le cas...
Ce qui semble poser problème, c'est bien que le GC ne semble pas s'occuper de mes instance "nullifiée".
Sinon, je n'ose pas une seconde creer autant d'instance de mon clip autant qu'il y a d'images, c'est pas propres et c'est loin du concept de dynamisme que doit prendre ma galerie...
 
Des questions me viennent, si je met toto = null; est-ce que le fait que toto contiennent des enfants rendrait la mise dans le GC impossible ? Je dis ça parcequ'en ce moment, c'est ce que j'ai fais, comme vous pouvez le voir, mais je n'ai pas encore fais quoi que ce soit qui s'occupe de rendre null tous le contenu...
Je pense à ça vu que tu as l'air de sous entendre que le fait de laisser un Timer fouterait la merde...
S'assurer de rendre null tous les enfants/propriétés d'un objet pour à son tour le rendre null, ça peut paraitre logique, n'empêche que je trouve ça contraignant...
En même temps, c'est ce que j'ai fait pour les vignettes (quand un dossier se replie)
Enfain, ça m'étonne que Flash n'est pas prévu le coup... une fonction qui se charge de détruire un objet, s'occupant donc automatiquement de ses enfants/Listener etc...


---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 23-02-2010 à 23:18:09   

Reply

Marsh Posté le 24-02-2010 à 00:02:02    

abais a écrit :

Je n'utilise pas de timer...
Ce que tu dis est valable si c'est la création en soit de mes instances qui est lourde, mais ce n'est pas le cas...
Ce qui semble poser problème, c'est bien que le GC ne semble pas s'occuper de mes instance "nullifiée".
Sinon, je n'ose pas une seconde creer autant d'instance de mon clip autant qu'il y a d'images, c'est pas propres et c'est loin du concept de dynamisme que doit prendre ma galerie...
 
Des questions me viennent, si je met toto = null; est-ce que le fait que toto contiennent des enfants rendrait la mise dans le GC impossible ? Je dis ça parcequ'en ce moment, c'est ce que j'ai fais, comme vous pouvez le voir, mais je n'ai pas encore fais quoi que ce soit qui s'occupe de rendre null tous le contenu...
Je pense à ça vu que tu as l'air de sous entendre que le fait de laisser un Timer fouterait la merde...
S'assurer de rendre null tous les enfants/propriétés d'un objet pour à son tour le rendre null, ça peut paraitre logique, n'empêche que je trouve ça contraignant...
En même temps, c'est ce que j'ai fait pour les vignettes (quand un dossier se replie)
Enfain, ça m'étonne que Flash n'est pas prévu le coup... une fonction qui se charge de détruire un objet, s'occupant donc automatiquement de ses enfants/Listener etc...


 
- La solution de préload n'est pas incompatible avec la notion de dynamisme.
- La solution que je te propose n'est pas à considérer comme une solution définitive, mais plutôt comme un teste à faire te permettant de valider ou pas ta théorie.
 
Si tu mets toto=null alors l'objet n'a plus de référence. Il est donc inaccessible. Le garbage collector va donc s'en occuper et libérer l'espace mémoire. S'il y a des objets fils, ils seront de fait éliminés aussi. Si tu tentes par la suite d'appeler une fonction d'un objet fils, tu soulèveras une exception du genre "null pointer exception".  
Si tu tentes de mettre à null un objet alors qu'il est utilisé, tu soulèveras aussi une exception.  
D'où l'utilité des try catch ;) Non seulement ca secure le code, mais aussi, et surtout, ça aide à voir où tu fais des erreurs quand tu debug :)
 
Pour ton problème, vu que t'utilises pas les timers, alors je penche comme Zed pour un problème de leak du coté de Away 3D.
Après, j'ai pas tout ton code sous le nez, si ça se trouve, ton problème est ailleurs et on regarde pas au bon endroit [:spamafote]


---------------
Free Daweed - "The game might crash, but at least the trains will run on time" - Chris Roberts 2018 - Je fais ma pute pour un Dragonfly : STAR-V6VM-MD7X
Reply

Marsh Posté le 24-02-2010 à 00:03:42    

Cherche dans les Frameworks je pense. Des fois j'utilise Guttershark et dedans y'a une classe pour mettre en cache et flush le cache. Je sais pas si ça fait ce que tu veux mais y doit bien y avoir des frameworks qui ont ce genre de fonctions ...


---------------
Jeu de simulation Boursière - Version BETA - https://www.facebook.com/wildstocks
Reply

Marsh Posté le 24-02-2010 à 08:32:35    

Attention !!! Quand tu fais monObjet = null, ce n'est pas l'objet que tu mets à null, mais la variable qui fait référence à cet objet.

 

(enfin c'est ce que je pense, mais si tu m'apporte la preuve du contraire).

Code :
  1. var sprite:Sprite = new Sprite();
  2. var sprite2:Sprite = sprite;
  3. sprite = null;
  4. trace(sprite2);
 

ferait bien l'affaire nan.
PS : j'ai trouvé ça : http://blog.comtaste.com/2008/04/g [...] h_pla.html

Message cité 1 fois
Message édité par gatsu35 le 24-02-2010 à 08:36:29

---------------
Blablaté par Harko
Reply

Marsh Posté le 24-02-2010 à 08:36:07    

Bon, j'ai soumis mon problème sur le forum de support Away3D...
J'espère qu'on comprendra mon anglais à chier...
 
Concernant le GC, j'ai lu assez de truc pour me convaincre que c'était assez bien foutu, donc je mets cette piste à l'écart...
J'ai toute mes raisons de penser que mon problème se situe dans ce que j'ai posté, vu que je ce sont les seules fonctions appelés pendant le test...
Il s'agit peut-être d'un problème d'Away3D, mais j'avoue que ça me dépasse...
 
Je vais faire en sorte que ce soit la même instance de mon movieClip qui fasse office de texture de toutes mes vignettes...  
J'enfermerai dedans les fonctions qui se chargeront de s'updater entre 2 vignettes...


---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 24-02-2010 à 08:41:47    

gatsu35 a écrit :

Attention !!! Quand tu fais monObjet = null, ce n'est pas l'objet que tu mets à null, mais la variable qui fait référence à cet objet.

 

un

Code :
  1. delete monObjet


ferait bien l'affaire nan.

 

J'avais essayer un delete, mais ça ne marche pas :
vignette3D.as(75): col: 11 Error: Attempt to delete the fixed property interactiveMC.  Only dynamically defined properties can be deleted.

 

Ma variable est en effet déclaré au pied de ma déclaration de class...
J'avais cru lire qu'en AS3, un delete ne faisait pas plus qu'un "null"  :(
Cependant quelque chose m'échappe... par dynamique, il entend que la variable soit déclaré au sein de ma fonction qui appelle le delete ?

Interessant ce qu'il dit sur les EventListener... je vais me pencher là dessus...
EDIT: Bon, j'ai mis les useWeakReference:Boolean à true; sur tous les addEventListener() de mes vignette3D
D'après l'article, c'est deja un bon pas vu que je recréé / effaces les vignette 3D à la volée...

Message cité 1 fois
Message édité par abais le 24-02-2010 à 09:11:18

---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 24-02-2010 à 09:55:54    

abais a écrit :

Je vais faire en sorte que ce soit la même instance de mon movieClip qui fasse office de texture de toutes mes vignettes...
J'enfermerai dedans les fonctions qui se chargeront de s'updater entre 2 vignettes...


Je m'auto-quote pour dire que ça fonctionne à merveille ainsi, je peux avoir une petite baisse de FPS mais ça remonte aussi tôt...
J'ai donc une seule instance de mon clip (un SWC fait avec flash), j'ai pris soint de lui mettre une fonction "build()" qui lui permet de se construire, et une fonction autodestroy() qui permet d'etre "nettoyé" où il faut entre 2 zoom de vignette...
Bon, ça règle mon problème, mais je ne comprends toujours pas pourquoi ce qu'il se passait... Je suis apparemment naïf de croire qu'en "null-ifiant" un objet, le CPU s'en déchargerait (le GC gérant derrière)


Message édité par abais le 24-02-2010 à 09:57:07

---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 24-02-2010 à 10:31:55    

abais a écrit :


Cependant quelque chose m'échappe... par dynamique, il entend que la variable soit déclaré au sein de ma fonction qui appelle le delete ?

 

Je pense que par dynamique, il veut dire que ta class doit être dynamique, de manière à pouvoir enlever et ajouter des propriétés facilement. (comme on pouvait le faire en AS2)

 

http://livedocs.adobe.com/flex/3/l [...] ml#dynamic

 

Sinon, bien joué pour ta solution ... c'est quand même un peu tordu (mais c'est pas de ta faute)

Message cité 2 fois
Message édité par Zedlefou le 24-02-2010 à 10:32:38

---------------
Jeu de simulation Boursière - Version BETA - https://www.facebook.com/wildstocks
Reply

Marsh Posté le 24-02-2010 à 11:16:31    

Zedlefou a écrit :


 
Je pense que par dynamique, il veut dire que ta class doit être dynamique, de manière à pouvoir enlever et ajouter des propriétés facilement. (comme on pouvait le faire en AS2)

En AS3, le template "dynamic" n'existe pas à la déclaration...
J'ai lu et relu à plusieurs endroit que "delete" ne s'utilisait pas en AS3...


---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Marsh Posté le 24-02-2010 à 11:17:28    

Zedlefou a écrit :


 
Je pense que par dynamique, il veut dire que ta class doit être dynamique, de manière à pouvoir enlever et ajouter des propriétés facilement. (comme on pouvait le faire en AS2)
 
http://livedocs.adobe.com/flex/3/l [...] ml#dynamic
 
Sinon, bien joué pour ta solution ... c'est quand même un peu tordu (mais c'est pas de ta faute)


C'est assez dégueulasse d'avoir un objet dynamique et c'est consomateur


---------------
Blablaté par Harko
Reply

Marsh Posté le 24-02-2010 à 12:08:58    

Merci en tout cas...
Je ne marque pas mon topic comme RESOLU car je considère que ça reste un mystère pour moi, mais je garde mon autre solution...
C'est la première fois que j'ai a supprimer des instances qui ne sont pas dans des conteneurs...

 

J'ai souvent eu à détruire des clips, le removeChild() (et le retrait des écouteurs dédiés) suffisait...
même lorsque qu'il s'agissait de particules que j'émettais/supprimais à la volé...

 

Ça m'a donc amené à une théorie : (j'aime bien faire des théories à 2 balles :D )
Le problème ici c'est justement qu'il n'y a pas d'addChild(), enfin, il y en a un forcément quelquepart mais c'est le framework Away3D qui s'en charge, moi je donne juste la class de mon clip à la création de mon MovieMaterial(clip:MovieClip)...
Je me suis donc re-re-re-plonger dans la doc d'Away3D et consulté toutes les methodes de cette class mais je n'ai rien trouvé...
Enfin bon, ça doit -etre un truc qui m'échape, un truc tout con si ça se trouve...
Si ma théorie était vrai, Away3D aurait ajouté une méthode pour palier ça...
Je fouillerais le setter de la class en question, de l'objet "movie"... En théorie, ils ont bien surement prévu de retirer le clip actuel avant d'en ajouter un autre... M'enfin...


Message édité par abais le 24-02-2010 à 12:11:03

---------------
Le membre ci-contre n'est pas responsable du message ci-dessus.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed