Suite à un projet qui demandait de modifier continuellement les propriétés de plusieurs composants visuel dans un MOUSE_MOVE
, j’ai du modifier le fonctionnement interne de ceux ci car le gaspillage des ressources était assez énorme.
Dans l’ancienne version des composants, à chaque modification de la valeur d’une propriété, le composant devait ce re-dessiner, hors si on modifie plusieurs propriétés a la suite le composant devait être redessiné pour chaque propriété …
Dans cette méthode (un simple exemple) exécuté par un MOUSE_MOVE
, 4 propriétés sont modifiés ce qui demande au composant de ce redessiner 4 fois : 3 fois de trop quand on recherche un usage modéré des ressources :
function evtStageMouseMove(ev:Event) { composant.couleurFond = _clrFond; composant.couleurTexte = _clrTexte; composant.couleurContour = _clrContour; composant.texte= _texte; }
Le probleme ce situe au niveau de la définition des propriétés, quand une propriété change de valeur, on demande au composant de ce re-dessiner :
public function set couleurFond(val:uint):void { if( this._clrFond != val ){ this._clrFond = val; this.dessiner();// méthode qui va dessiner le composant } }
Pour éviter l’effet indésirable il ne faut plus appeler la méthode qui dessine le composant dans le « setter », mais plutôt enregistrer un évènement pour que le composant sache qu’il doit ce redessiner lorsque la tête de lecture change de « frame », de cette façon on peut ce permettre de modifier plusieurs propriétés à la suite avec une seule re-création visuelle, donc plus le composant est complexe et plus l’économie de ressource est grande !
Les modifications à apporter sont simples :
- Enregistrement d’un évènement
ENTER_FRAME
dés qu’une propriété est modifié. - Dans l’
ENTER_FRAME
on appelle la méthode qui doit créer le composant. - Effacement de l’évènement
ENTER_FRAME
aprés la re-création du composant.
// un "setter" d'une propriété quelconque public function set couleurFond(val:uint):void { if( this._clrFond != val ){ this._clrFond = val; this.redessiner();// méthode qui va enregistrer l'évènement ENTER_FRAME } } // enregistrement de l'évènement ENTER_FRAME private function redessiner():void { this.addEventListener(Event.ENTER_FRAME, dessiner); } // méthode utilisé pour dessiner le composant private function dessiner(ev:Event = null):void { // Faire ici tous les ajouts des éléments graphique + tous les dessins voulu pour créer le visuel du composant // ..... // effacer l'évènement ENTER_FRAME this.removeEventListener(Event.ENTER_FRAME, dessiner); }
J’ai chronométré l’ancienne façon de faire et la nouvelle pour vérifier les apports des modifications, le résultat est éloquent :
pour 7 propriétés à modifier pour 1 composant, le tout exécuté 1000 fois de suite dans une boucle (vitesse swf = 30ips)
ancien système : 1922 Millieme (1,9 sec)
nouveau système : 100 Millieme (0,1 sec)
Les modifications ont permis de diviser par 19 le temps utilisé par le composant pour sa création .. c’est loin d’être négligeable
Il existe plein d’autres manières d’économiser des ressources et la plupart sont tout à fait logique, tel que :
- Ne pas utiliser un
Sprite
quand unShape
suffit. - Ne pas utiliser un
MovieClip
quand unSprite
suffit -> Il est d’ailleurs très rare d’avoir besoin deMovieClip
pour un composant visuel et pourtant il suffit de faire une recherche sur google code pour remarquer qu’un gros paquet des composants visuels actionscript utilisentMovieClip
comme classe mère, pourtant quasiment aucun de ces composants utilisent les propriétés/méthodes propre àMovieClip
. - Éviter les composants adobe, ils sont bons, complets mais lourd.
- Ne pas utiliser un
ENTER_FRAME
quand unMOUSE_MOVE
suffit. - Limiter le nombre et l’utilisation des
TextField
, cette classe est très lourde. - Quand c’est possible il faut déclarer les classes et méthodes avec le mot clé
final
(permet au compilateur de faire un gros travail d’optimisation). - Éviter tant que possible les méthodes de la classe
Math
(la plupart peuvent être remplacés facilement avec un peu de code, tel quemin
/max
/sqrt
/abs
). - …etc