Flex Debug – Garbage Collector AS3 et Flash Player 9
Quand vous développez des applications Flex lourdes, il est important de vérifier la place que votre application tient en mémoire. Si votre application prend de plus en plus de place mémoire, elle sera ralentie et l'expérience utilisateur sera plus laborieuse. Ces fuites de mémoire sont appelées "Memory Leaks".
Pour voir quelle place votre application Flex tient dans la mémoire, vous pouvez simplement ouvrir le Gestionnaire de tâches (Task Manager) sous Windows et dans la partie processus, vous pourrez voir quelle place prend votre navigateur (iexplore.exe pour Internet Explorer et firefox.exe pour Firefox).
Au fur et à mesure que vous allez utiliser votre application, cette mémoire va grossir puisque vous allez allouer de nouveaux blocs mémoire pour vos objets. Mais alors, comment faire baisser cette allocation de mémoire? Et bien il suffit de libérer la mémoire allouée pour des objets qui ne sont plus utilisés. Par exemple, dans votre application Flex, vous ajoutez une ComboBox puis vous la supprimez, elle n'a plus de raison de rester dans la mémoire. C'est là qu'intervient le Garbage Collector AS3.
Le Garbage Collector (GC) parcourt votre application à intervalles non réguliers (et non prévisibles) à la recherche de variables en mémoire qui ne sont plus référencées par votre application. Si elle n'a plus de référence, elle va être supprimée de la mémoire par le Garbage Collector.
Pour stabiliser la charge de votre application en mémoire, il faut bien comprendre comment fonctionne le Garbage Collector. Une fois que vous aurez compris ces mécanismes, vous pourrez aussi utiliser le Flex Profiler pour allez plus loin et chasser ces fuites mémoire de manières plus efficace.
Le Garbage Collector AS3 en bref
Le GC est un processus de fond qui enlève de la mémoire les objets qui ne sont plus utilisés par l'application. Un objet inactif est un objet qui n'a plus de références vers lui depuis des objets actifs. Pour comprendre cela, il est très important de comprendre que quand on travaille avec des types non-primitifs (tout sauf Boolean, String, Number, uint, int), on est toujours en train de passer des références à cet objet, et pas l'objet lui-même. Supprimer une variable supprime la référence, pas l'objet.
En voici la démonstration simple:
// créer un nouvel objet, et le référencer comme a
var a:Object = {foo:"bar"}
// copier la référence de cet objet dans b
var b:Object = a;
// supprimer la référence vers l'objet dans a
delete(a);
// vérifier si l'objet est toujours référencé par b
trace(b.foo); // affiche "bar", donc l'objet existe toujours
Si l'on supprimait "b" aussi dans l'exemple ci-dessus, cela laisserait mon objet sans références actives et permettrait de le libérer pour la garbage collection. Le Garbage Collector utilise deux méthodes pour identifier les objets qui n'ont plus de références actives: Comptage de référence (Reference Counting) et Mark Sweeping.
Comptage de référence (Reference Counting)
Le comptage de référence est une des méthodes les plus simples pour garder une trace des références actives, et a été utilisé par Flash depuis l'AS1. Quand vous créez une référence vers un objet, son compteur de référence est incrémenté. Quand vous supprimez une référence, il est décrémenté. Si le compteur de référence atteint zéro, il est marqué comme supprimable par le GC.
Par exemple:
var a:Object = {foo:"bar"}
// l'objet a maintenant un nombre de référence égal à 1 (a)
var b:Object = a;
// maintenant il a un nombre de référence égal à 2 (a&b)
delete(a);
// retour à 1 (b)
delete(b);
// retour à 0, l'objet peut maintenant être supprimé de la mémoire par le GC
Le comptage de référence est simple, ne surcharge pas le CPU, et fonctionne bien dans la plupart des situations. Cependant, on peut voir facilement une faille quand on a des références circulaires. Cela se produit quand les objets se référencent entre eux (directement ou indirectement via d'autre objets). Même si l'application n'utilise plus activement ces objets, leur compteur de référence reste au-dessus de 0, donc ils ne sont jamais supprimés.
Voici la démonstration de ces références circulaires:
var a:Object = {}
//créer un second objet, et référencer le premier objet:
var b:Object = {foo:a};
/ faire que le premier objet référence aussi le second
a.foo = b;
// supprimer les des références actives:
delete(a);
delete(b);
Dans l'exemple ci-dessus, les deux références active de mon application ont été supprimées. On n'a plus aucun moyen d'accéder à ces deux objets depuis mon application mais leur compteur de référence est toujours à 1 car ils se référencent entre eux. Cela peut devenir bien plus complexe (a référence c, qui référence b, qui référence a, etc.). Flash Player 6 et 7 ont souffert de ces problèmes liés aux références circulaires dans les objets XML (chaque node XML référençait à la fois son enfant et son parent), qui n'étaient jamais supprimés de la mémoire. Heureusement, Flash Player 8 a ajouté une nouvelle technique de Garbage Collection appelée Mark Sweeping
Mark Sweeping
La seconde stratégie employée par le Garbage Collector AS3 (et FP8) pour trouver les objets est le "mark sweeping". Le player commence au nœud racine (root) de votre application (qui est appelé "root" en AS3), et et passe par toutes les références qu'il contient, et marque chaque objet qu'il trouve. Il itère ensuite parmi chaque objet marqué et marque ses enfants. Il continue cela de manière récursive jusqu'à ce qu'il ait traversé l'arbre d'objet entier de votre application, marquant tout ce qu'il trouve. A la fin de ce processus, il peut assumer de manière certaine que les objets en mémoire qui ne sont pas marqués n'ont plus de références actives, et peuvent être enlevés de la mémoire. Vous pouvez voir comment cela fonctionne sur le schéma suivant: les références vertes ont été suivies pendant le Mark Sweeping. Les objets verts sont marqués, les objets blanc seront supprimés de la mémoire.
Le Mark Sweeping fonctionne très bien, mais comme il doit traverser l'ensemble de la structure, il est aussi assez coûteux en ce qui concerne l'utilisation du CPU. Flash Player 9 réduit ce coût en faisant un Mark Sweeping de manière itérative (c'est-à-dire qu'il se produit sur un certain nombre d'image, au lieu de tout en une seule fois), et le Mark Sweeping ne se produit qu'occasionnellement.
Report de Garbage Collection et indétermination
Une chose très importante à comprendre à propos du Garbage Collector de Flash Player 9, est que ses opérations sont reportées. Vos objets ne seront pas supprimés immédiatement de la mémoire immédiatement après que toutes les références actives aient été supprimées, elles seront supprimées à un temps indéterminé dans le futur.
Le GC va regarder l'allocation de la RAM et la taille de la pile mémoire (entre autres) pour déterminer quand il doit être exécuté. En tant que développeur, vous devez accepter le fait que vous n'avez aucun moyen de savoir quand (ou même si) vos objets inactifs vont être supprimés de la mémoire. Vous devez aussi savoir que les objets inactifs vont continuer à s'exécuter indéfiniment (jusqu'à ce que le GC les supprime), donc le code va continuer à s'exécuter (par exemple, les enterFrames), les sons seront encore joués, les évènements seront toujours dispatchés, etc.
Il est très important de se rappeler que vous n'avez pas le contrôle sur le moment où vos objets seront supprimés de la mémoire, donc vous devez les rendre aussi inertes que possible quand vous en avez fini avec eux (il existe cependant un hack en faisant une double LocalConnection qui permet de déclencher le GC mais il n'est pas conseillé de l'utiliser en production).
Source: http://www.gskinner.com
Articles similaires
- Flex Debug – Garbage Collector AS3: Gestion des ressources
- Flex Profiler – Optimiser votre application Flex avec le Profiler de Flex Builder 3 (Partie 2)
- Flex Modules – Décharger (Unload) correctement ses modules
- Adobe Air – Composant mx:HTML avec contenu SWF et Garbage Collection
- Flex ActionScript – Manipulation d'évènements (Event) en ActionScript 3







7 décembre 2008
Merci pour cette intro au garbage collecteur. je trouve de plus en plus que Flex est une alternative très riche à Flash.
Je crois que je vais m'y mettre.
9 décembre 2008
Très utile, toute foi on ne sais pas comment l'utiliser.
Merci
gg
9 décembre 2008
Salut,
je suis en train d'écrire d'autres articles sur la gestion des ressources AS3 et comment éviter ces fuites mémoire.
il seront publiés dans les prochains jours
fabien
12 décembre 2008
Pour savoir comment utiliser efficacement le Garbage Collector et optimiser ses applications Flex 3, voici la suite de l'article:
http://www.flex-tutorial.fr/2008/12/12/flex-debug-garbage-collector-as3-gestion-des-ressources/
fabien