Actionscript 3.0 Optimization: en praktisk Example

ActionScript 3,0 Optimization: Et praktisk eksempel
Del
Del
22
Del
Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av

Kode optimalisering mål å maksimere ytelsen til Flash eiendeler, mens du bruker så lite av systemets ressurser -. RAM og CPU - som mulig. I denne opplæringen starter med en fungerende, men ressurs hogging Flash app, vil vi gradvis gjelde mange optimalisering tweaks til kildekoden, til slutt ender opp med en raskere, slankere SWF.




Endelig resultat Forhåndsvisning

La oss ta en titt på det endelige resultatet vi skal jobbe mot:

Merk at "Minne brukt "og" CPU Load "statistikken er basert på all den SWF du har åpne på tvers av alle nettleservinduer, inkludert Flash bannerannonser og lignende. Dette kan gjøre SWF vises mer ressurskrevende enn den faktisk er



Trinn 1:. Forstå Flash Movie

Flash movie har to hovedelementer: en partikkel simulering av brann, og en graf som viser animasjonen ressursforbruk over tid. Grafen rosa linje sporer totalt minne forbrukes av filmen i megabyte, og den grønne linjen tomter CPU belastning i prosent.

Action gjenstander ta opp det meste av minnet allokert til Flash Player, og jo mer Action objekter en film inneholder, jo høyere minneforbruk. For å holde et programmets minneforbruket lavt, Flash Player gjør regelmessig noen søppelrydding ved å feie gjennom alle Action gjenstander og slippe fra minnet de som ikke lenger er i bruk.

En minneforbruket Grafen viser normalt en kupert opp- ned mønster, dyppe hver gang søppelrydding er utført, deretter sakte stiger etter hvert som nye objekter opprettes. En graf linje som bare kommer opp poeng til et problem med søppelrydding, så det betyr nye objekter blir lagt til minnet, mens ingen blir fjernet. Dersom en slik trend fortsetter, kan Flash-spilleren til slutt krasje som den går tom for minne.

CPU belastning beregnes ved å spore filmens bildefrekvens. En Flash filmens bildefrekvens er mye som sin hjerterytme. Med hver beat, de Flash Player oppdateringer og gjengir alt på skjermen elementer og kjører også eventuelle nødvendige Action oppgaver.

Det er bildefrekvensen som bestemmer hvor mye tid Flash Player skal bruke på hver beat, så en ramme hastighet på 10 bilder per sekund (fps) betyr minst 100 millisekunder per beat. Dersom alle de nødvendige oppgavene utføres innen den tid, da Flash Player vil vente på den gjenværende tiden til å gå før du går videre til neste beat. På den annen side, hvis de nødvendige oppgaver i en bestemt rytme er for CPU intensive skal være ferdig innen gitt tidsramme, bremser deretter bildefrekvensen automatisk ned for å gi litt ekstra tid. Når belastningen lysere, bildefrekvens hastigheter opp igjen, tilbake til innstilt hastighet.

(Bildefrekvensen kan også automatisk strupes ned til 4 fps av Flash Player når programmets overordnede vinduet mister fokus eller går offscreen . Dette gjøres for å spare systemressurser når brukerens oppmerksomhet er rettet andre steder)

Hva dette betyr er at det er faktisk to typer bildefrekvens. den du opprinnelig satt og håper filmen kjører alltid på , og en det faktisk
kjører på. Vi kaller det satt av deg målrette
bildefrekvens, og en det faktisk går på faktiske
frame rate.

Grafen CPU belastning beregnes som forholdet mellom faktisk å målrette bildefrekvens. Formelen som brukes for å beregne dette er:

CPU load = (target frame rate - selve bildefrekvens) /faktiske bildefrekvens * 100

For eksempel, hvis målet bildefrekvensen er satt til 50 bilder per sekund men filmen faktisk kjører på 25fps, CPU belastning vil være 50% - det vil si, (50 - 25) /50 * 100.

Vær oppmerksom på at dette ikke er den faktiske andelen av systemet CPU-ressursene som brukes av løpe filmen, men heller et grovt estimat av den faktiske verdien. For optimalisering prosessen skissert her, er dette anslaget en god nok metrisk for oppgaven. For å få den faktiske CPU-bruk, bruke verktøy levert av operativsystemet, f.eks Oppgavebehandling i Windows. Ser på meg det akkurat nå, viser det unoptimized filmen bruker 53% av CPU-ressurser, mens filmens grafen viser en CPU belastning på 41,7%.

MERK: Alle filmskjermbilder i denne opplæringen ble tatt fra den frittstående versjonen av Flash Player. Grafen vil mest sannsynlig vise ulike tall på systemet, avhengig av operativsystem, nettleser og Flash Player versjon. Å ha noen andre som kjører Flash apps i forskjellige nettleservinduer eller flash-spillere kan også påvirke bruken minne rapportert av noen systemer. Når analysere perfomance av programmet, må du alltid sørge for at ingen andre Flash programmer kjører som de kan ødelegge dine beregninger.

Med CPU belastning, forventer at det å skyte opp til over 90% når filmen går av skjermen - for eksempel hvis du bytter til en annen nettleser fane eller bla nedover siden. Jo lavere bildefrekvens som forårsaker dette vil ikke være forårsaket av CPU intensive oppgaver, men av Flash strupe ned bildefrekvensen når du ser andre steder. Når dette skjer, må du vente noen sekunder for CPU belastning grafen for å avgjøre til sin rette CPU belastningsverdier etter de vanlige bildefrekvens spark i



Trinn 2:. Betyr Denne koden Make My Flash Look Fat?

Filmen kildekode er vist nedenfor, og inneholder bare én klasse, oppkalt Flames, som også er dokumentet klasse. Klassen inneholder et sett med egenskaper til å holde styr på filmen minne og CPU belastning historie, som deretter brukes til å tegne en graf. De minne og CPU belastning statistikken er beregnet og oppdatert i de Flames.getStats () -metoden, og grafen tegnes ved å ringe Flames.drawGraph () på hver ramme. For å lage en brann effekt, Flames.createParticles () -metoden første genererer hundrevis av partikler som hver andre, som er lagret i fireParticles matrisen. Denne rekken blir deretter sendes gjennom av Flames.drawParticles (), som bruker hver partikkel egenskaper for å skape effekten.

Ta deg tid til å studere Flames klassen. Kan du allerede oppdage eventuelle raske endringer som vil gå langt i å optimalisere programmet
pakken com.pjtops {import flash.display.MovieClip;? Import flash.events.Event, importere fl.motion.Color, importere flash. geom.Point, import flash.geom.Rectangle, import flash.text.TextField, import flash.system.System, import flash.utils.getTimer; public class Flames strekker MovieClip {private Var memoryLog = new Array (); //Lagrer System.totalMemory verdier for visning i grafen private Var memoryMax = 0; //Den høyeste verdien av System.totalMemory registrert så langt privat Var memoryMin = 0; //Den laveste verdien av System.totalMemory registrert så langt private Var memoryColor; //Fargen som brukes av tekst vise minne info private Var flått = 0; //Teller antall ganger getStats () kalles før neste frame rate verdien er satt private Var framerate = 0; //den opprinnelige bildefrekvens verdi som ligger i Adobe Flash private Var cpuLog = new Array (); //Butikker cpu verdier for visning i grafen private Var cpuMax = 0; //Høyeste cpu verdien registreres så langt privat Var cpuMin = 0; //Den laveste cpu verdien registreres så langt private Var cpuColor; //Fargen som brukes av tekst viser cpu private Var cpu; //Dagens beregnede cpu bruk private Var lastUpdate = 0; //Siste gang framerate ble beregnet private Var sampleSize = 30; //Lengden av memoryLog &Co. cpuLog private Var graphHeight; private Var graphWidth; private Var fireParticles = new Array (); //Lagrer alle aktive flamme partikler private Var fireMC = new MovieClip (); //Lerretet for å tegne flammene private Var palett = new Array (); //Lagrer alle tilgjengelige farger for flammen partikler private Var ankere = new Array (); //Butikker horisontale punkter langs fireMC som fungerer som magneter til partikler private Var ramme; //De movieclips markeringsrammen //klassen konstruktør. Sett opp alle hendelser, tidtakere og objekter offentlig funksjon Flames () {addChildAt (fireMC, 1); frame = new rektangel (2, 2, stage.stageWidth - 2, stage.stageHeight - 2); Var colWidth = Math.floor (frame.width /10); for (var i = 0, jeg < 10; i ++) {ankere [i] = Math.floor (i * colWidth); } SetPalette (); memoryColor = memoryTF.textColor; cpuColor = cpuTF.textColor; graphHeight = graphMC.height; graphWidth = graphMC.width; Framerate = stage.frameRate; addEventListener (Event.ENTER_FRAME, drawParticles); addEventListener (Event.ENTER_FRAME, getStats); addEventListener (Event.ENTER_FRAME, DrawGraph); } //Skaper en samling av farger for flamme partikler, og lagrer dem i paletten privat funksjon setPalette () {var svart = 0x000000; Var blå = 0x0000FF; Var rød = 0xff0000; Var orange = 0xFF7F00; Var gul = 0xFFFF00; Var hvit = 0xFFFFFF; palett = palette.concat (getColorRange (svart, blå, 10)); palett = palette.concat (getColorRange (blå, rød, 30)); palett = palette.concat (getColorRange (rød, oransje, 20)); palett = palette.concat (getColorRange (oransje, gul, 20)); palett = palette.concat (getColorRange (gul, hvit, 20)); } //Returnerer en samling av farger, laget av forskjellige blandinger av farger1 og color2 privat funksjon getColorRange (Farge1, color2, trinn) {var output = new Array (); for (var i = 0; i < trinn; i ++) {var fremgang = i /trinn; Var color = Color.interpolateColor (farger1, color2, fremdrift); output.push (farge); } Returnere utgang; } //Beregner statistikk for den nåværende tilstanden i programmet, i form av minne som brukes og cpu% private funksjons getStats (event) {flått ++; Var nå = getTimer (); if (nå - lastUpdate < 1000) {return; } else {lastUpdate = nå; } Cpu = 100 - flått /framerate * 100; cpuLog.push (cpu); flått = 0; cpuTF.text = cpu.toFixed (1) + '%'; if (cpu > cpuMax) {cpuMax = cpu; cpuMaxTF.text = cpuTF.text; } If (cpu < cpuMin || cpuMin == 0) {cpuMin = cpu; cpuMinTF.text = cpuTF.text; } Var minne = System.totalMemory /1000000; memoryLog.push (minne); memoryTF.text = String (memory.toFixed (1)) + 'mb'; if (minne > memoryMax) {memoryMax = minne; memoryMaxTF.text = memoryTF.text; } If (minne < memoryMin || memoryMin == 0) {memoryMin = minne; memoryMinTF.text = memoryTF.text; }} //Gjengi er en graf på skjermen, som viser utviklingen i applikasjoner bildefrekvens og minneforbruk privat funksjon DrawGraph (hendelse) {graphMC.graphics.clear (); Var ypoint, xpoint; Var logSize = memoryLog.length; if (logSize > sampleSize) {memoryLog.shift (); cpuLog.shift (); logSize = sampleSize; } Var widthRatio = graphMC.width /logSize; graphMC.graphics.lineStyle (3, memoryColor, 0,9); Var memoryRange = memoryMax - memoryMin; for (var i = 0; i < memoryLog.length; i ++) {ypoint = (memoryLog [i] - memoryMin) /memoryRange * graphHeight; xpoint = (i /sampleSize) * graphWidth; if (i == 0) {graphMC.graphics.moveTo (xpoint, -ypoint); fortsette; } GraphMC.graphics.lineTo (xpoint, -ypoint); } GraphMC.graphics.lineStyle (3, cpuColor, 0,9); for (var j = 0; j < cpuLog.length; j ++) {ypoint = cpuLog [j] /100 * graphHeight; xpoint = (j /sampleSize) * graphWidth; if (j == 0) {graphMC.graphics.moveTo (xpoint, -ypoint); fortsette; } GraphMC.graphics.lineTo (xpoint, -ypoint); }} //Gjengir hver flamme partikkel og oppdateringer det verdier private funksjons drawParticles (event) {createParticles (20); fireMC.graphics.clear (); for (var i i fireParticles) {var partikkel = fireParticles [i]; if (particle.life == 0) {delete (fireParticles [i]); fortsette; } Var size = Math.floor (particle.size * particle.life/100); Var color = palett [particle.life]; Var transperency = 0,3; if (størrelse < 3) {size * = 3; color = 0x333333; particle.x + = Math.random () * 8 - 4; particle.y - = 2; transperency = 0,2; } else {particle.y = frame.bottom - (100 - particle.life); if (particle.life > 90) {size * = 1,5; } else if (particle.life > 45) {particle.x + = Math.floor (Math.random () * 6 - 3); størrelse * = 1,2; } else {transperency = 0,1; størrelse * = 0,3; particle.x + = Math.floor (Math.random () * 4 - 2); }} FireMC.graphics.lineStyle (5, farge, 0,1); fireMC.graphics.beginFill (farge, transperency); fireMC.graphics.drawCircle (particle.x, particle.y, størrelse); fireMC.graphics.endFill (); particle.life--; }} //Genererer flamme partikkel objekter private funksjons createParticles (count) {var anchorPoint = 0; for (var i = 0; i < telle; i ++) {var partikkel = new Object (); particle.x = Math.floor (Math.random () * frame.width /10) + ankere [anchorPoint]; particle.y = frame.bottom; particle.life = 70 + Math.floor (Math.random () * 30); particle.size = 5 + Math.floor (Math.random () * 10); fireParticles.push (partikkel); if (particle.size > 12) {particle.size = 10; } Particle.anchor = ankere [anchorPoint] + Math.floor (Math.random () * 5); anchorPoint = (anchorPoint == 9)? 0: anchorPoint + 1; }}}}

Det er mye å ta i, så ikke bekymre deg - vi vil gå gjennom de ulike forbedringer i resten av denne opplæringen



Trinn 3:. Bruk Strong Typing Ved å tildele datatyper til alle variabler

Den første endringen vi gjør i klassen er å spesifisere datatypen alle deklarerte variabler, metodeparametre og metodereturverdier.

For eksempel Endring av dette
beskyttet Var memoryLog = new Array (); beskyttet Var memoryMax = 0; //Ja, men hva er du

til dette
beskyttet Var memoryLog: Array = new Array ();?. beskyttet Var memoryMax: Antall = 0; //MemoryMax nummer, mye bedre!

Når erklære variabler, alltid angi datatype, da dette gjør at Flash kompilatoren å utføre noen ekstra optimaliseringer ved generering av SWF-fil. Dette alene kan føre til store ytelsesforbedringer, som vi vil snart se med vårt eksempel. En annen ekstra fordelen av sterk typing er at kompilatoren vil fange og varsle deg om eventuelle datatype relaterte bugs



Trinn 4:. Undersøke Resultater

Dette skjermbildet viser den nye Flash film, etter påføring sterk typing. Vi kan se at selv om den har hatt noen virkning på den aktuelle eller maksimal CPU-belastning, har den minste verdien falt fra 8,3% til 4,2%. Maksimalt minne forbrukes har gått ned fra 9 MB til 8.7MB.

skråningen av grafen minne linje har også endret seg, i forhold til det som er vist i trinn 2. Den har fortsatt den samme taggete mønster, men nå synker og stiger langsommere. Dette er en god ting, hvis du tenker på at de plutselige fall i minneforbruk er forårsaket av Flash Player er søppelrydding, som vanligvis utløses når allokert minne er i ferd med å renne ut. Denne søppelrydding kan bli en dyr operasjon, ettersom Flash Player har å traversere gjennom alle objektene, på jakt etter de som ikke lenger er nødvendig, men fortsatt tar opp minne. Jo mindre ofte det har å gjøre dette, jo bedre



Trinn 5:. Effektivt Lagre numeriske data

Action gir tre numeriske datatyper: Antall, UINT og int. Av de tre typene, forbruker nummer mest minne som den kan lagre numeriske verdier større enn de to andre. Det er også den eneste typen stand til å lagre tall med desimaltall fraksjoner.

The Flames klasse har mange numeriske egenskaper, som alle bruker Antall datatype. Som int og uint er mer kompakte datatyper, kan vi spare minne ved å bruke dem i stedet for tall i alle situasjoner der vi ikke trenger desimalbrøker.

Et godt eksempel er i looper og Array indekser, så for eksempel vi skal endre
for (var i: Number = 0, jeg < 10; i ++) {ankere [i] = Math.floor (i * colWidth);}

inn
for (var i: int = 0, jeg < 10; i ++) {ankere [i] = Math.floor (i * colWidth);}

egenskaper cpu, cpuMax og memoryMax vil forbli Numbers, som de vil mest sannsynlig lagre brøk data, mens memoryColor, cpuColor og flått kan endres til uints, som de vil alltid lagre positive, hele tall



Trinn 6:. Minimer Metode Calls

Metode samtaler er dyrt, spesielt kalle en metode fra en annen klasse. Det blir verre hvis den klassen tilhører en annen pakke, eller er en statisk metode. Det beste eksempelet her er Math.floor () metoden, som brukes i hele Flames klassen til roundoff brøk tall. Denne metoden samtalen kan unngås ved å bruke uints stedet for tall for å lagre hele tall.
//Så i stedet for å: ankere [i] = Math.floor (i * colWidth); //vi i stedet kastet verdien til en uintanchors [i] = uint (i * colWidth); //Samme optimalisering kan utføres ved ganske enkelt å tildele uint datatype, for eksempel changingvar størrelse: uint = Math.floor (particle.size * particle.life/100); //inn Div størrelse: uint = particle.size * particle.life/100;

I eksempelet ovenfor, er kallet til Math.floor () unødvendig, ettersom Flash vil automatisk avrunde noen brøktallverdi tildelt en uint



Trinn 7: Multiplikasjon er raskere. enn Division

Flash Player tilsynelatende finner multiplikasjon enklere enn divisjon, så vi vil gå gjennom Flames klassen og konvertere alle divisjon matematikk i tilsvarende multiplikasjon math. Konverteringen formel innebærer å få den gjensidige av nummeret på høyre side av drift, og multiplisere det med nummeret til venstre. Den gjensidige av en rekke beregnes ved å dele en med dette antallet
Var colWidth. Uint = frame.width /10; //divisjon med tenvar colWidth: uint = frame.width * 0,1; //gir samme resultat som multiplikasjon med 0,1

La oss ta en rask titt på resultatene av våre siste optimalisering innsats. CPU-belastningen har endelig forbedret ved å slippe fra 41,7% til 37,5%, men minneforbruket forteller en annen historie. Maksimalt minne har steget til 9.4MB, det høyeste nivået ennå, og grafen er skarpe, sag-tann kanter viser at søppelrydding blir kjørt oftere igjen. Noen optimaliseringsteknikker vil ha denne inverse effekt på hukommelsen og CPU-belastning, forbedrer en på bekostning av den andre. Med minneforbruk nesten tilbake til utgangspunktet, fortsatt trenger mye mer arbeid som må gjøres



Trinn 8:. Gjenvinning er bra for miljøet

Du kan også spille en del i å redde miljøet. Resirkulere gjenstander når du skriver din AS3 kode redusere mengden strøm som forbrukes av programmene dine. Både etablering og ødeleggelse av nye objekter er dyre operasjoner. Hvis programmet er stadig å skape og ødelegge gjenstander av samme type, kan store ytelsesforbedringer oppnås ved å resirkulere disse objektene i stedet. Ser på Flames klasse, kan vi se at mye av partikkel gjenstander blir skapt og ødelagt hvert sekund:
private funksjons drawParticles (event): void {createParticles (20); fireMC.graphics.clear (); for (var i: * i fireParticles) {var partikkel: Object = fireParticles [i]; if (particle.life == 0) {delete (fireParticles [i]); fortsette; }

Det er mange måter å resirkulere gjenstander, de fleste innebære å skape en ny variabel til å lagre unødvendige gjenstander i stedet for å slette dem. Deretter når en ny gjenstand av samme type er påkrevet, hentes fra lageret i stedet for å opprette en ny. Nye objekter opprettes bare når butikken er tom. Vi kommer til å gjøre noe lignende med partikkel objekter av Flames klassen.

Først oppretter vi en ny rekke kalt inactiveFireParticles [], som lagrer referanser til partikler hvis liv eiendommen er null (døde partikler). I drawParticles () metoden, i stedet for å slette en død partikkel, vi legger det til inactiveFireParticles [] rekke
private funksjons drawParticles (event). Void {createParticles (20); fireMC.graphics.clear (); for (var i: * i fireParticles) {var partikkel: Object = fireParticles [i]; if (particle.life < = 0) {if (particle.life == 0) {particle.life = 1; inactiveFireParticles.push (partikkel); } Fortsette; }

Neste, vi endre createParticles () metode for å først sjekke for eventuelle lagrede partikler i inactiveFireParticles [] array, og bruke dem alle før å skape noen nye partikler
private funksjons createParticles (teller). void {var anchorPoint = 0; for (var i: uint = 0; i < telle; i ++) {var partikkel: Object; if (inactiveFireParticles.length > 0) {partikkel = inactiveFireParticles.shift (); } else {partikkel = new Object (); fireParticles.push (partikkel); } Particle.x = uint (Math.random () * frame.width * 0,1) + ankere [anchorPoint]; particle.y = frame.bottom; particle.life = 70 + uint (Math.random () * 30); particle.size = 5 + uint (Math.random () * 10); if (particle.size > 12) {particle.size = 10; } Particle.anchor = ankere [anchorPoint] + uint (Math.random () * 5); anchorPoint = (anchorPoint == 9)? 0: anchorPoint + 1; }}



Trinn 9: Bruk Object og Array Literaler når det er mulig

Når du oppretter nye objekter eller arrays, ved hjelp av den bokstave syntaks er raskere enn å bruke den nye operatøren
private Var memoryLog.: Array = new Array (); //Utvalg opprettet ved hjelp av ny operatorprivate Var memoryLog: Array = []; //Utvalg opprettet ved hjelp av raskere rekke literalparticle = new Object (); //Objekt opprettet ved hjelp av ny operatorparticle = {}; //Objekt opprettet ved hjelp av raskere protestere bokstave



Trinn 10: Unngå å bruke Dynamiske Classes

Klasser i Action kan enten være forseglet eller dynamiske. De er forseglet som standard, noe som betyr at de eneste egenskapene og metodene til et objekt avledet fra det kan ha må ha blitt definert i klassen. Med dynamiske klasser, kan nye egenskaper og metoder legges under kjøring. Sealed klasser er mer effektiv enn dynamiske klasser, fordi noen Flash Player ytelsesoptimaliseringer som kan gjøres når all mulig funksjonalitet som en klasse noen gang kan ha er kjent på forhånd.

I flammene klasse, tusener av partiklene utvide det innebygde objektklasse, som er dynamisk. Siden ingen nye egenskaper må legges til en partikkel under kjøring, vil vi spare opp mer ressurser ved å opprette en egendefinert forseglet klasse for partiklene.

Her er den nye partikkel, som har blitt lagt til samme Flames.as filen
klasse Particle {public var x. UINT; offentlig Var y: UINT; offentlig Var liv: int; offentlig Var størrelse: Number; offentlig Var anker: uint;}

De createParticles () metoden vil også bli justert, endre linjen
Var partikkel: Object; partikkel = {};

til stedet lese:
Var partikkel: Partikkel; partikkel = new Particle ();



Trinn 11: Bruk Sprites når du ikke trenger den Tidslinje

I likhet med Object klassen, movieclips er dynamiske klasser. Den MovieClip klassen arver fra Sprite klasse, og den største forskjellen mellom de to er at MovieClip har en tidslinje. Siden Sprites har all funksjonaliteten til movieclips minus tidslinjen, kan du bruke dem når du trenger en Displayobject som ikke trenger tidslinjen. The Flames klassen utvider MovieClip men det trenger ikke bruke tidslinjen, som all sin animasjon styres gjennom Actionscript. Brann partikler blir trukket på fireMC, som også er en MovieClip som ikke gjør bruk av sin tidslinje

Vi endrer både Flames og fireMC å forlenge Sprite stedet, erstatter.
Import flash.display.MovieClip; private Var fireMC: MovieClip = new MovieClip (); public class Flames strekker MovieClip {

med
import flash.display.Sprite; privat Var fireMC: Sprite = new Sprite (); public class Flames strekker Sprite {



Trinn 12: Bruk Shapes stedet for Sprites Når du ikke trenger Child Skjerm Objekter eller Mouse Input

The Shape klassen er enda lettere enn Sprite klasse, men det kan ikke støtte mus hendelser eller inneholde barnevisningsobjekter. Som fireMC krever ingenting av denne funksjonaliteten, kan vi trygt slå den inn i en form
import flash.display.Shape; privat Var fireMC. Shape = new Shape ();

Grafen viser store forbedringer i minneforbruk , med det slippe og resterende stabilt på 4.8MB. De sag-tann kanter har blitt erstattet av en nesten rett horisontal linje, noe som betyr at søppelrydding er nå sjelden kjørt. Men CPU lasten har stort sett gått tilbake igjen til sin opprinnelige høyt nivå på 41,7%



Trinn 13:. Unngå komplekse beregninger Inside Loops

De sier over 50% av et program tid er brukt i gang 10% av sin kode, og det meste av den 10% er mest sannsynlig til å bli tatt opp av sløyfer. Mange sløyfe optimalisering teknikker innebærer å plassere så mye av CPU-intensive operasjoner utenfor kroppen av en loop. Disse operasjonene omfatter objekt skapelse, variable oppslag og beregninger
for. (Var i = 0; i < memoryLog.length; i ++) {//løkke kroppen}

Den første sløyfen i DrawGraph () metoden er vist over. Løkken går gjennom hvert element av memoryLog array, bruker hver verdi å plotte punkter på grafen. Ved starten av hvert forsøk, det ser opp lengden av memoryLog matrise og sammenligner den med den sløyfetelleren. Hvis memoryLog matrisen har 200 elementer, kjører sløyfe 200 ganger, og utfører den samme oppslaget 200 ganger. Siden lengden av memoryLog ikke endrer seg, de gjentatte oppslag er uøkonomisk og unødvendig. Det er bedre å slå opp verdien av memoryLog.length bare en gang før oppslaget begynner og lagre den i en lokal variabel, siden tilgang til en lokal variabel vil være raskere enn å få tilgang til et objekt eiendom
Var memoryLogLength. Uint = memoryLog.length; for (var i = 0; i < memoryLogLength; i ++). {//løkke kroppen}

I Flames klassen, vi justere de to looper i DrawGraph () -metoden som vist ovenfor



Trinn 14: Plasser betinget utsagn mest sannsynlig til å være sant First

Tenk blokken av if..else conditionals nedenfor, avledet fra drawParticles () metode:
if (particle.life > 90) {//en rekkevidde på 10 verdier, mellom 91 - 100 størrelse * = 1,5;} else if (particle.life > 45) {//et utvalg av 45 verdier, mellom 46-90 particle.x + = Math .random () * 6 - 3; størrelse * = 1,2;} else {//et utvalg av 45 verdier, verdier mellom 0-45 transperency = 0,1; størrelse * = 0,3; particle.x + = Math.random () * 4 - 2;}

En partikkel liv verdien kan være et tall mellom 0 og 100. hvis klausul tester om dagens partikkel liv er mellom 91-100, og i så fall den utfører koden i den blokken. Den else-if klausul tester for en verdi mellom 46 og 90, mens annet klausul tar de gjenværende verdiene, er de mellom 0 og 45. Med tanke på første sjekk også den minst sannsynlighet for å lykkes som den har den minste rekke tall, det bør være den siste tilstanden testet. Blokken omskrives som vist nedenfor, slik at den mest sannsynlige betingelser blir behandlet først, noe som gjør evalueringene mer effektiv
if (particle.life < 46). {Transperency = 0,1; størrelse * = 0,3; particle.x + = Math.random () * 4 - 2;} else if (particle.life < 91) {particle.x + = Math.random () * 6 - 3; størrelse * = 1,2;} else {size * = 1,5; }



Trinn 15: Legg Elements til slutten av en Array Uten Pushing

Metoden Array.push () er brukt ganske mye i Flames klassen. Det vil bli erstattet av en raskere teknikk som bruker rekken lengde eiendom
cpuLog.push (CPU).; //Treg og prettycpuLog [cpuLog.length] = cpu; //Rask og stygg

Når vi vet lengden på array, kan vi erstatte Array.push () med en enda raskere teknikk, som vist nedenfor
Var utgang. Array = []; //utgang er en ny, tom array. Lengden er 0 for (var i: uint = 0; i < trinn; i ++) {//verdien av jeg også starter på null. Hver sløyfe syklus øker både jeg og output.length etter én Var pågår: Antall = I /trinn; Var farge: uint = Color.interpolateColor (farger1, color2, fremdrift); utgang [i] = farge; //Raskere enn cpuLog [cpuLog.length] = cpu; }



Trinn 16: Bytt Arrays med vektorer

Array og Vector klasser er svært like, med unntak av to store forskjeller: Vektorer kan bare lagre objekter av samme type, og de er mer effektiv og raskere enn matriser. Siden alle arrays i flammene klassen enten lagre variabler av bare én type - ints, uints eller partikler, som nødvendig - vi skal konvertere dem alle til vektorer

Disse arrays.
Private Var memoryLog: Array = []; privat Var cpuLog: Array = []; private Var fireParticles: Array = []; private Var palett: Array = []; private Var ankere: Array = []; private Var inactiveFireParticles: Array = [];

... er erstattet med sine Vector ekvivalenter:
private Var memoryLog. Vector < Number > . = New Vector < Number > (); privat Var cpuLog: Vector < Number >. Number >; = new Vector <. (); private Var fireParticles: Vector < Partikkel >. = New Vector. ≪ Particle > (); private Var palett: Vector < UINT >. = New Vector. ≪ UINT > (); private Var ankere: Vector < UINT >. . = New Vector < uint > (); private Var inactiveFireParticles. Vector < Particle > . = New Vector < Particle > ();

Så vi endre getColorRange () metode for å jobbe med vektorer i stedet arrays
privat funksjons getColorRange (Farge1, color2, trinn):.. Vector < UINT > {var utgang. Vector < UINT > = New Vector. ≪ UINT > (); for (var i: uint = 0; i < trinn; i ++) {var fremgang: Number = i /trinn; Var farge: uint = Color.interpolateColor (farger1, color2, fremdrift); utgang [i] = farge; } Returnere utgang; }



Trinn 17: Bruk hendelses Model Sparsomt

Mens svært praktisk og hendig, er AS3 Hendelses modell bygget på toppen av en forseggjort oppsett av hendelsen lyttere, dispatchers og objekter; så er tilfelle forplantning og boblende og mye mer, alle som en bok kan skrives om. Når det er mulig, alltid ringe en metode direkte i stedet for gjennom hendelsen modellen
addEventListener (Event.ENTER_FRAME, drawParticles);. AddEventListener (Event.ENTER_FRAME, getStats); addEventListener (Event.ENTER_FRAME, DrawGraph);

The Flames klasse har tre hendelsen lyttere ringer tre ulike metoder, og alle bundet til ENTER_FRAME hendelsen. I dette tilfellet kan vi holde det første arrangementet lytteren og kvitte seg med de to andre, så har de drawParticles () -metoden samtale getStats (), som i sin tur kaller DrawGraph (). Alternativt kan vi bare lage en ny metode som kaller getStats (), DrawGraph () og drawParticles () for oss direkte, så har bare én hendelse lytteren som er bundet til den nye metoden. Det andre alternativet er dyrere imidlertid så vi vil holde med den første
//denne linjen blir lagt før slutten av den. ≪ code > drawParticles < /code > () methodgetStats (); //Denne linjen blir lagt før slutten av < code > getStats () < /code > methoddrawGraph ();

Vi fjerner også tilfelle parameter (som holder hendelses objekt) fra både DrawGraph () og getStats (), da de ikke lenger er nødvendig



Trinn 18:. Deaktiver alle Muse Hendelser for skjermobjekter som ikke trenger det

Siden dette Flash-animasjon ikke krever noen form for brukermedvirkning, kan vi frigjøre sin skjerm objekt fra utsendelse unødvendige mus hendelser.