ActionScript 3
Optimera prestanda
Sök…
Vektorbaserad grafik
Vektorbaserad grafik representeras av en mängd data som måste beräknas av CPU (vektorpunkter, bågar, färger osv.). Allt annat än enkla former med minimala punkter och raka linjer kommer att konsumera stora mängder CPU-resurs.
Det finns en "Cache som bitmapp" -flagga som kan aktiveras. Denna flagga lagrar resultatet av att rita det vektorbaserade DisplayObject för mycket snabbare ritningar. Fallgropen med detta är att om det finns några transformationer som tillämpas på objektet, måste hela saken ritas om och cache-cache. Detta kan vara långsammare än att inte sätta på det alls om det används ram-för-ram-transformationer (rotation, skalning osv.).
Generellt är rendering av grafik med bitmapp mycket mer utförande än med vektorgrafik. Bibliotek som flixel drar nytta av detta för att göra spriter på en "duk" utan att minska framerate.
Text
Rendering av text förbrukar mycket CPU. Teckensnitt återges på ett sätt som liknar vektorgrafik och innehåller många vektorpoäng för varje tecken. Att ändra text ram för ram kommer att försämra prestandan. Flaggan "Cache som bitmapp" är extremt användbar om den används korrekt, vilket innebär att du måste undvika:
- Ändrar texten ofta.
- Transformera textfältet (rotera, skala).
Enkla tekniker som inpackning av textuppdateringar i ett if
uttalande kommer att göra en stor skillnad:
if (currentScore !== oldScore) {
field.text = currentScore;
}
Text kan återges med hjälp av den anti-alias renderaren inbyggd i Flash eller med "enhetssnitt". Att använda "enhetssteckensnitt" gör att text återges mycket snabbare, även om det gör att text verkar trasslig (alias). Dessutom kräver enhetsteckensnitt att teckensnittet ska förinstalleras av din slutanvändare, eller texten kan "försvinna" på användarens dator även om det verkar bra på din.
field.embedFonts = false; // uses "device fonts"
Vektor och för varje vs-matriser och för
Använda Vector.<T>
-typen och for each
slinga är mer utförande än en konventionell matris och for
slinga:
Bra:
var list:Vector.<Sprite> = new <Sprite>[];
for each(var sprite:Sprite in list) {
sprite.x += 1;
}
Dålig:
var list:Array = [];
for (var i:int = 0; i < list.length; i++) {
var sprite:Sprite = list[i];
sprite.x += 1;
}
Snabbt borttagning av arrayobjekt
Om du inte behöver ett array för att vara i någon särskild ordning, kommer ett litet trick med pop()
att ge dig enorma prestandaförhållanden jämfört med splice()
.
När du delar upp splice()
en matris måste indexet för efterföljande element i den arrayen minskas med 1. Den här processen kan konsumera en stor del av tiden om matrisen är stor och objektet du tar bort är närmare början på den arrayen .
Om du inte bryr dig om ordningen på elementen i matrisen kan du istället ersätta det objekt du vill ta bort med ett objekt som du pop()
från slutet av matrisen. På detta sätt förblir indexen för alla andra artiklar i matrisen densamma och processen försämras inte när det gäller prestanda när längden på din grupp växer.
Exempel:
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();
}
}
}
Vektorer istället för Arrays
Flash Player 10 introducerade Vector. <*> Generisk listtyp som var snabbare än Array. Detta är dock inte helt sant. Endast följande vektortyper är snabbare än Array-motsvarigheterna på grund av hur de implementeras i Flash Player.
-
Vector.<int>
- Vektor av 32-bitars heltal -
Vector.<uint>
- Vektor av 32-bitars heltal som inte är signerade -
Vector.<Double>
- Vektor av 64-bitars flottörer
I alla andra fall kommer en Array att vara mer performant än att använda Vectors för alla operationer (skapande, manipulation, etc). Men om du vill "starkt skriva" din kod kan du använda vektorer trots avmattningen. FlashDevelop har en syntax som möjliggör att rullgardinsmenyerna för fullbordad kod fungerar även för Arrays med /*ObjectType*/Array
.
var wheels:Vector.<Wheel> // strongly typed, but slow
var wheels:/*Wheel*/Array // weakly typed, but faster
Återanvända och samla grafik
Att skapa och konfigurera Sprite
och TextField
objekt under körning kan vara kostsamt om du skapar hundratusentals av dessa på en enda ram. Därför är ett vanligt trick att "poola" dessa objekt för senare återanvändning. Kom ihåg att vi inte bara försöker optimera skapandetiden ( new Sprite()
) utan också konfigurationen (inställning av standardegenskaper).
Låt oss säga att vi byggde en listkomponent med hundratals TextField-objekt. När du behöver skapa ett nytt objekt, kontrollera om ett befintligt objekt kan återanvändas.
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);
Senare, när du förstör din komponent (eller tar bort den från skärmen), kom ihåg att lägga till oanvända etiketter tillbaka i poolen.
foreach (var label in allLabels){
label.parent.removeChild(label); // remove from parent Sprite
pool.push(label); // add to pool
}
I de flesta fall är det bäst att skapa en pool per användning istället för en global pool. Nackdelar med att skapa en global pool är att du måste initialisera objektet varje gång för att hämta det från poolen, för att förneka inställningarna som görs av andra funktioner. Detta är lika kostsamt och förnekar ganska mycket prestandaförstärkningen av att använda pooling i första hand.