ActionScript 3
Optimiser les performances
Recherche…
Graphiques vectoriels
Les graphiques vectoriels sont représentés par une multitude de données qui doivent être calculées par le processeur (points vectoriels, arcs, couleurs, etc.). Tout ce qui n'est pas des formes simples avec des points et des lignes droites minimes consomme de grandes quantités de ressources du processeur.
Il existe un indicateur "Cache as Bitmap" qui peut être activé. Cet indicateur stocke le résultat du dessin de l'objet DisplayObject vectoriel pour des retraits beaucoup plus rapides. Le problème est que si des transformations sont appliquées à l’objet, l’ensemble doit être redessiné et remis en cache. Cela peut être plus lent que de ne pas l'activer du tout si des transformations image par image sont appliquées (rotation, mise à l'échelle, etc.).
Généralement, le rendu graphique à l'aide de bitmaps est beaucoup plus performant que l'utilisation de graphiques vectoriels. Les bibliothèques telles que flixel en profitent pour rendre les sprites sur un "canvas" sans réduire le framerate.
Texte
Le rendu du texte consomme beaucoup de CPU. Les polices sont rendues de la même manière que les graphiques vectoriels et contiennent de nombreux points vectoriels pour chaque caractère. La modification du texte image par image va dégrader les performances. L'indicateur "Cache as bitmap" est extrêmement utile s'il est utilisé correctement, ce qui signifie que vous devez éviter:
- Modifier le texte fréquemment.
- Transformation du champ de texte (rotation, mise à l'échelle).
Des techniques simples comme l’enrobage de mises à jour de texte dans une instruction if
feront une différence majeure:
if (currentScore !== oldScore) {
field.text = currentScore;
}
Le texte peut être rendu en utilisant le moteur de rendu anti-aliasé intégré à Flash ou en utilisant les "polices de périphérique". L'utilisation de "polices de périphérique" rend le rendu du texte beaucoup plus rapide, bien qu'il rende le texte irrégulier (aliasé). De plus, les polices de périphérique requièrent que la police soit pré-installée par votre utilisateur final, ou le texte risque de «disparaître» sur le PC de l'utilisateur, même s'il semble correct sur le vôtre.
field.embedFonts = false; // uses "device fonts"
Vecteur et pour chaque vs tableaux et pour
En utilisant le type Vector.<T>
et le for each
boucle est plus performant qu'un tableau conventionnel et for
boucle:
Bien:
var list:Vector.<Sprite> = new <Sprite>[];
for each(var sprite:Sprite in list) {
sprite.x += 1;
}
Mal:
var list:Array = [];
for (var i:int = 0; i < list.length; i++) {
var sprite:Sprite = list[i];
sprite.x += 1;
}
Suppression rapide d'éléments de tableau
Si vous n'avez pas besoin d'un tableau dans un ordre particulier, une petite astuce avec pop()
vous permettra de gagner énormément en performance par rapport à splice()
.
Lorsque vous splice()
un tableau, l'index des éléments suivants de ce tableau doit être réduit de 1. Ce processus peut consommer une grande partie du temps si le tableau est volumineux et que l'objet que vous supprimez est plus proche du début de ce tableau. .
Si vous ne vous souciez pas de l'ordre des éléments du tableau, vous pouvez remplacer l'élément que vous souhaitez supprimer par un élément que vous pop()
à la fin du tableau. De cette manière, les index de tous les autres éléments du tableau restent les mêmes et le processus ne se dégrade pas au fur et à mesure que la longueur de votre tableau augmente.
Exemple:
function slowRemove(list:Array, item:*):void {
var index:int = list.indexOf(item);
if (index >= 0) list.splice(index, 1);
}
function fastRemove(list:Array, item:*):void {
var index:int = list.indexOf(item);
if (index >= 0) {
if (index === list.length - 1) list.pop();
else {
// Replace item to delete with last item.
list[index] = list.pop();
}
}
}
Vecteurs au lieu de tableaux
Flash Player 10 a introduit le type de liste générique Vector. <*> Plus rapide que le tableau. Cependant, ce n'est pas tout à fait vrai. Seuls les types de vecteur suivants sont plus rapides que les homologues Array, en raison de leur implémentation dans Flash Player.
-
Vector.<int>
- Vecteur d'entiers 32 bits -
Vector.<uint>
- Vecteur d'entiers non signés 32 bits -
Vector.<Double>
- Vecteur de flottants 64 bits
Dans tous les autres cas, l'utilisation d'un tableau sera plus performante que l'utilisation des vecteurs, pour toutes les opérations (création, manipulation, etc.). Cependant, si vous souhaitez "taper fortement" votre code, vous pouvez utiliser les vecteurs malgré le ralentissement. FlashDevelop a une syntaxe qui permet aux /*ObjectType*/Array
déroulantes d'achèvement du code de fonctionner même pour les tableaux, en utilisant /*ObjectType*/Array
.
var wheels:Vector.<Wheel> // strongly typed, but slow
var wheels:/*Wheel*/Array // weakly typed, but faster
Réutilisation et regroupement des graphiques
La création et la configuration d'objets Sprite
et TextField
au moment de l'exécution peuvent être coûteux si vous en créez des centaines de milliers sur une seule image. Par conséquent, une astuce courante consiste à "regrouper" ces objets pour les réutiliser ultérieurement. Rappelez-vous que nous n'essayons pas seulement d'optimiser le temps de création ( new Sprite()
) mais aussi la configuration (paramétrage des propriétés par défaut).
Disons que nous construisions un composant de liste à l'aide de centaines d'objets TextField. Lorsque vous devez créer un nouvel objet, vérifiez si un objet existant peut être réutilisé.
var pool:Array = [];
if (pool.length > 0){
// reuse an existing TextField
var label = pool.pop();
}else{
// create a new TextField
label = new TextField();
// initialize your TextField over here
label.setDefaultTextFormat(...);
label.multiline = false;
label.selectable = false;
}
// add the TextField into the holder so it appears on-screen
// you will need to layout it and set its "text" and other stuff seperately
holder.addChild(label);
Plus tard, lorsque vous détruisez votre composant (ou le supprimez de l'écran), n'oubliez pas d'ajouter des étiquettes inutilisées dans le pool.
foreach (var label in allLabels){
label.parent.removeChild(label); // remove from parent Sprite
pool.push(label); // add to pool
}
Dans la plupart des cas, il est préférable de créer un pool par utilisation au lieu d'un pool global. Inconvénients de la création d'un pool global: vous devez réinitialiser l'objet à chaque fois pour le récupérer à partir du pool, pour annuler les paramètres définis par d'autres fonctions. Ceci est tout aussi coûteux et nie en grande partie le gain de performance lié à l'utilisation de la mise en commun en premier lieu.