Optimisations diverses

Pour un objet TextField, utilisez la méthode appendText() plutôt que l’opérateur += .

Lorsque vous utilisez la propriété text de la classe TextField, préférez la méthode appendText() à l’opérateur += . Cette méthode garantit de meilleures performances.

Le code suivant, par exemple, utilise l’opérateur += et il faut 1 120 ms pour exécuter la boucle :

addChild ( myTextField ); 
  
myTextField.autoSize = TextFieldAutoSize.LEFT; 
var started:Number = getTimer(); 
  
for (var i:int = 0; i< 1500; i++ ) 
{ 
    myTextField.text += "ActionScript 3"; 
} 
  
trace( getTimer() - started ); 
// output : 1120 

Dans l’exemple ci-dessous, nous avons remplacé l’opérateur += par la méthode appendText() :

var myTextField:TextField = new TextField(); 
addChild ( myTextField ); 
myTextField.autoSize = TextFieldAutoSize.LEFT; 
  
var started:Number = getTimer(); 
  
for (var i:int = 0; i< 1500; i++ ) 
{ 
    myTextField.appendText ( "ActionScript 3" ); 
} 
 
trace( getTimer() - started ); 
// output : 847 

Le code s’exécute à présent en 847 ms.

Si possible, mettez à jour les champs de texte en dehors des boucles.

Il est possible d’optimiser encore plus ce code par le biais d’une technique simple. La mise à jour du champ de texte dans chaque boucle met trop à contribution les ressources de traitement internes. Il suffit de concaténer une chaîne et de l’attribuer à la valeur du champ de texte en dehors de la boucle pour réduire considérablement la durée d’exécution du code, qui correspond maintenant à 2 ms :

var myTextField:TextField = new TextField(); 
addChild ( myTextField ); 
myTextField.autoSize = TextFieldAutoSize.LEFT; 
 
var started:Number = getTimer(); 
var content:String = myTextField.text; 
  
for (var i:int = 0; i< 1500; i++ ) 
{ 
    content += "ActionScript 3"; 
} 
  
myTextField.text = content; 
  
trace( getTimer() - started ); 
// output : 2 

Lors de l’utilisation de texte HTML, la première technique est tellement lente qu’elle renvoie parfois une exception Timeout dans Flash Player, dans certaines situations. Ce peut être le cas, par exemple, lorsque le matériel sous-jacent est trop lent.

Remarque : Adobe® AIR® ne renvoie pas cette exception.
var myTextField:TextField = new TextField(); 
addChild ( myTextField ); 
myTextField.autoSize = TextFieldAutoSize.LEFT; 
  
var started:Number = getTimer(); 
  
for (var i:int = 0; i< 1500; i++ ) 
{ 
    myTextField.htmlText += "ActionScript <b>2</b>"; 
} 
 
trace( getTimer() - started ); 

Attribuez une valeur à une chaîne en dehors de la boucle et le code s’exécute en 29 ms seulement :

var myTextField:TextField = new TextField(); 
addChild ( myTextField ); 
myTextField.autoSize = TextFieldAutoSize.LEFT; 
  
var started:Number = getTimer(); 
var content:String = myTextField.htmlText; 
  
for (var i:int = 0; i< 1500; i++ ) 
{ 
    content += "<b>ActionScript<b> 3"; 
} 
  
myTextField.htmlText = content; 
  
trace ( getTimer() - started ); 
// output : 29 
Remarque : dans Flash Player 10.1 et AIR 2.5, la classe String a été améliorée de façon à ce que les chaînes soient moins gourmandes en mémoire.
Evitez si possible d’utiliser l’opérateur crochet.

L’utilisation de l’opérateur crochet peut ralentir les performances. Pour éviter de vous en servir, vous pouvez stocker votre référence dans une variable locale. Le code suivant illustre une utilisation peu performante de l’opérateur crochet :

var lng:int = 5000; 
var arraySprite:Vector.<Sprite> = new Vector.<Sprite>(lng, true); 
var i:int; 
  
for ( i = 0; i< lng; i++ ) 
{ 
    arraySprite[i] = new Sprite(); 
} 
  
var started:Number = getTimer(); 
  
for ( i = 0; i< lng; i++ ) 
{ 
    arraySprite[i].x = Math.random()*stage.stageWidth; 
    arraySprite[i].y = Math.random()*stage.stageHeight; 
    arraySprite[i].alpha = Math.random(); 
    arraySprite[i].rotation = Math.random()*360; 
} 
  
trace( getTimer() - started ); 
// output : 16 

La version optimisée de cet exemple, ci-dessous, contient moins d’opérateurs crochet :

var lng:int = 5000; 
var arraySprite:Vector.<Sprite> = new Vector.<Sprite>(lng, true); 
var i:int; 
  
for ( i = 0; i< lng; i++ ) 
{ 
    arraySprite[i] = new Sprite(); 
} 
  
var started:Number = getTimer(); 
var currentSprite:Sprite; 
  
for ( i = 0; i< lng; i++ ) 
{ 
    currentSprite = arraySprite[i]; 
     currentSprite.x = Math.random()*stage.stageWidth; 
     currentSprite.y = Math.random()*stage.stageHeight; 
     currentSprite.alpha = Math.random(); 
     currentSprite.rotation = Math.random()*360; 
} 
  
trace( getTimer() - started ); 
// output : 9 
Placez le code en ligne, si possible, pour réduire le nombre d’appels de fonctions qu’il contient.

Les appels de fonctions sont gourmands en ressources. Réduisez autant que faire se peut le nombre de ces appels en plaçant le code en ligne. Ce faisant, vous optimiserez vraiment les performances. Tenez néanmoins compte du fait qu’il peut être plus difficile de réutiliser du code en ligne et que la taille du fichier SWF risque d’augmenter. Il est facile de déplacer en ligne des appels de fonctions tels que les méthodes de la classe Math. Le code suivant s’appuie sur la méthode Math.abs() pour calculer des valeurs absolues :

const MAX_NUM:int = 500000; 
var arrayValues:Vector.<Number>=new Vector.<Number>(MAX_NUM,true); 
var i:int; 
  
for (i = 0; i< MAX_NUM; i++) 
{ 
    arrayValues[i] = Math.random()-Math.random(); 
} 
  
var started:Number = getTimer(); 
var currentValue:Number; 
  
for (i = 0; i< MAX_NUM; i++) 
{ 
    currentValue = arrayValues[i]; 
    arrayValues[i] = Math.abs ( currentValue ); 
} 
  
trace( getTimer() - started ); 
// output : 70

Vous pouvez réaliser manuellement le calcul effectué par Math.abs() et le placer en ligne :

const MAX_NUM:int = 500000; 
var arrayValues:Vector.<Number>=new Vector.<Number>(MAX_NUM,true); 
var i:int; 
  
for (i = 0; i< MAX_NUM; i++) 
{ 
    arrayValues[i] = Math.random()-Math.random(); 
} 
  
var started:Number = getTimer(); 
var currentValue:Number; 
  
for (i = 0; i< MAX_NUM; i++) 
{ 
    currentValue = arrayValues[i]; 
    arrayValues[i] = currentValue > 0 ? currentValue : -currentValue; 
} 
  
trace( getTimer() - started ); 
// output : 15

En conséquence du déplacement en ligne de l’appel de fonction, le code est plus de quatre fois plus rapide. Cette technique est préconisée dans de nombreux cas, mais pensez aux effets possibles sur la réutilisation et la maintenabilité du code.

Remarque : la taille du code a une grande incidence sur l’exécution globale du lecteur. Si l’application comprend beaucoup de code ActionScript, il faut longtemps à la machine virtuelle pour vérifier le code et effectuer une compilation juste à temps (JIT). Les recherches de propriétés peuvent être lentes, en raison de la complexité accrue des hiérarchies d’héritage et parce que les mémoires cache ont tendance à être plus sollicitées. Pour réduire la taille du code, évitez d’utiliser la structure Adobe® Flex®, la bibliothèque de structures TLF ou toute bibliothèque ActionScript tierce de grande taille.
Evitez également les boucles d’évaluation des instructions.

Une autre mesure d’optimisation consiste à ne pas évaluer une instruction dans une boucle. Le code suivant effectue des itérations sur un tableau mais il n’est pas optimisé, car la longueur du tableau est évaluée à chaque fois :

for (var i:int = 0; i< myArray.length; i++) 
{ 
}

Il est préférable de stocker la valeur et de la réutiliser :

var lng:int = myArray.length; 
 
for (var i:int = 0; i< lng; i++) 
{ 
}
Utilisez l’ordre inverse dans les boucles while.

Une boucle while en ordre inverse est beaucoup plus rapide :

var i:int = myArray.length; 
 
while (--i > -1) 
{ 
}

Ces astuces proposent quelques techniques d’optimisation d’ActionScript et illustrent l’impact d’une simple ligne de code sur les performances et la mémoire. Il en existe toutefois beaucoup d’autres. Pour plus d’informations, voir le lien suivant : http://www.rozengain.com/blog/2007/05/01/some-actionscript-30-optimizations/ (disponible en anglais uniquement).