Minimera processoranvändning

Ytterligare ett viktigt område att fokusera på är processoranvändningen. Genom att optimera processoranvändningen förbättras prestandan, vilket i sin tur resulterar i bättre batterieffektivitet i mobila enheter.

Förbättrad processoranvändning i Flash Player 10.1

I Flash Player 10.1 introduceras två nya funktioner som leder till mindre processorutnyttjande. Funktionerna omfattar att pausa och återuppta SWF-innehåll när det hamnar utanför skärmen och att begränsa antalet Flash Player-instanser på en sida.

Pausa, strypa och återuppta

Obs! Funktionen för att pausa, strypa och återuppta gäller inte Adobe® AIR®-program.

För att optimera processor- och batteriutnyttjande introduceras i Flash Player 10.1 en ny funktion, som rör hanteringen av inaktiva instanser. Den här funktionen använder du för att begränsa processoranvändningen genom att pausa och återta SWF-filen när innehållet visas och tas bort från skärmen. Med den här funktionen kommer Flash Player att frigöra så mycket minneskapacitet som möjligt genom att ta bort objekt som kan återskapas när det spelade innehållet återtas. Innehåll anses vara utanför skärmen när hela innehållet är utanför.

Det kan finnas två anledningar till varför SWF-innehåll kommer utanför skärmen:

  • Användaren rullar sidan vilket leder till att SWF-innehållet hamnar utanför skärmen.

    På det viset fortsätter eventuellt ljud- och videoinnehåll att spelas upp men återgivningen stoppas. Om ljud eller video inte spelas upp ska du ställa in HTML-parametern hasPriority på true så att uppspelningen eller körningen av ActionScript inte pausas. Du bör dock tänka på att SWF-innehåll som återges kommer att pausas när innehåll är utanför skärmen eller dolt, oberoende av värdet för HTML-parametern hasPriority .

  • En flik öppnas i webbläsaren och SWF-innehållet flyttas till bakgrunden.

    I det här fallet, och oavsett vad värdet på HTML-taggen hasPriority är, saktas SWF-innehållet ned eller stryps till mellan 2 och 8 bildrutor i sekunden. Ljud- och videouppspelningen stoppas och ingen innehållsåtergivning bearbetas förrän SWF-innehållet blir synligt igen.

För Flash Player 11.2 och senare versioner på stationära Windows- och Mac-datorer kan du använda ThrottleEvent i programmet. Flash Player skickar en ThrottleEvent när Flash Player pausar, stryper eller återupptar uppspelningen.

ThrottleEvent är en s.k. utsändningshändelse, vilket betyder att den skickas av alla EventDispatcher-objekt som har en avlyssnare registrerad för den här händelsen. Du hittar mer information om utsändningshändelser i avsnittet om klassen DisplayObject .

Instanshantering

Obs! Funktionen för instanshantering gäller inte Adobe® AIR®-program.
Använd HTML-parametern hasPriority för att fördröja inläsningen av SWF-filer som ligger utanför skärmen.

I Flash Player 10.1 introduceras en ny HTML-parameter med namnet hasPriority :

<param name="hasPriority" value="true" />

Den här funktionen använder du för att begränsa antalet Flash Player-instanser som startas på en sida. Genom att begränsa antalet instanser får du bättre processor- och batterikapacitet. Syftet är att tilldela SWF-innehåll speciella prioriteringar och att ge visst innehåll företräde före annat innehåll på en sida. Tänk dig följande enkla exempel: En användare tittar på en webbplats och indexsidan innehåller tre olika SWF-filer. En av dem visas, en annan är delvis synlig och den tredje är utanför skärmen, och han/hon behöver rulla. De båda första animeringarna startar normalt, men den sista fördröjs tills den blir synlig. Detta scenario är standardbeteende när parametern hasPriority inte är närvarande eller inställd på false . Om du vill vara säker på att SWF-filen startas, även när den inte visas, anger du att parametrarna hasPriority ska vara true . Oberoende av värdet på parametern hasPriority så kommer emellertid återgivningen av en SWF-fil som inte visas ständigt att vara tillfälligt stoppad.

Obs! Om processorresurserna börjar ta slut kommer ingen Flash Player-instans att startas automatiskt, även om parametern hasPriority är true . Om nya instanser skapas med JavaScript sedan sidan lästs in, kommer dessa instanser att ignorera hasPriority -flaggan. Allt pixelinnehåll på 1x1 eller 0x0 startas och förhindrar att hjälp-SWF-filer kommer att fördröjas om webbmastern inte inkluderar hasPriority -flaggan. SWF-filer startas emellertid fortfarande när användaren klickar på dem. Detta beteende kallas ”click to play” på engelska.

I bilden nedan visas effekten när du ställer in olika värden för parametern hasPriority :

Effekten av olika värden för parametern hasPriority

Effekten av olika värden för parametern hasPriority

Viloläge

I Flash Player 10.1 och AIR 2.5 introduceras en ny funktion för mobilenheter, som bidrar till att minska processorbearbetningen och därmed förlänger batteriets livstid. Funktionen arbetar med bakgrundsbelysningen som finns i många mobilenheter. Om en användare som kör ett mobilprogram till exempel störs och slutar använda telefonen, identifierar körningsmiljön att bakgrundsbelysningen försätts i viloläge. Bildrutefrekvensen minskar då till 4 bildrutor i sekunden (fps) och återgivningen pausas. För AIR-program inleds viloläget också när programmet placeras i bakgrunden.

ActionScript-koden kommer att fortsätta att köras i viloläget som om du ställde in egenskapen Stage.frameRate till 4 bildrutor per sekund. Däremot kommer återgivningen att stoppas så användaren kommer inte att se att spelaren körs med 4 bildrutor per sekund. En bildrutefrekvens på 4 bildrutor per sekund valdes, och inte noll, eftersom detta innebär att alla anslutningar förblir öppna (NetStream, Socket och NetConnection). Att byta till noll skulle innebära att öppna anslutningar skulle avbrytas. Ett uppdateringsintervall på 250 ms har valts (4 bildrutor per sekund), eftersom många enhetstillverkare använder denna bildrutefrekvens som uppdateringsintervall. Med det här värdet får körningsmiljön och enheten ungefär samma bildrutefrekvens.

Obs! När körningsmiljön är i viloläge returnerar egenskapen Stage.frameRate bildrutefrekvensen för den ursprungliga SWF-filen, i stället för 4 bildrutor per sekund.

När bakgrundsbelysningen aktiveras på nytt återtas återgivningen. Bildrutefrekvensen återgår till det ursprungliga värdet. Tänk dig en mediespelare där musik spelas. Om skärmen försätts i viloläge svarar körningsmiljön på detta utifrån den typ av innehåll som spelas upp. Nedan följer en lista över situationer och motsvarande beteende för körningsmiljön:

  • Bakgrundsbelysningen försätts i viloläge och inget ljud-/videoinnehåll spelas upp: Återgivningen pausas och bildrutefrekvensen anges till 4 bildrutor per sekund.

  • Bakgrundsbelysningen försätts i viloläge och ljud-/videoinnehåll spelas upp: Bakgrundsbelysningen fortsätter att vara aktiverad och användarupplevelsen fortsätter.

  • Bakgrundsbelysningen går från viloläge till aktivt läge: Bildrutefrekvensen ställs in på den ursprungliga SWF-filens inställning och återgivningen fortsätter.

  • Flash Player pausas medan ljud-/videoinnehåll spelas upp: Bakgrundsbelysningen återställs till standardsystembeteendet, eftersom ljud/video inte längre spelas upp.

  • Mobilenheten tar emot ett telefonsamtal medan ljud-/videoinnehåll spelas upp: Återgivningen pausas och bildrutefrekvensen anges till 4 bildrutor per sekund.

  • Bakgrundsbelysningens viloläge inaktiveras på en mobilenhet: Körningsmiljön fungerar som vanligt.

När bakgrundsbelysningen försätts i viloläge pausas återgivningen och bildrutefrekvensen går långsammare. Den här funktionen sparar på processorkapaciteten, men det går inte att förlita sig på den för att skapa en verklig paus, som exempelvis i ett spel.

Obs! Ingen ActionScript-händelse skickas när körningsmiljön försätts i eller tas ur viloläge.

Frysa och tina upp objekt

Frys ned och tina upp objekt med hjälp av händelserna REMOVED_FROM_STAGE och ADDED_TO_STAGE .

Om du vill optimera koden ska du alltid frysa och tina upp dina objekt. Det är viktigt för alla objekt att de kan frysas och tinas upp, men detta är speciellt viktigt för visningsobjekt. Även om visningsobjekten inte längre finns i visningslistan och väntar på att samlas in med skräpinsamlaren, kan de ändå använda kod som är processorintensiv. De kan till exempel fortfarande använda Event.ENTER_FRAME. Detta resulterar i att det är viktigt att frysa och tina upp objekt på ett korrekt sätt med händelserna Event.REMOVED_FROM_STAGE och Event.ADDED_TO_STAGE . I följande exempel visas en interaktion mellan ett filmklipp som spelas upp på scenen och tangentbordet:

// Listen to keyboard events 
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyIsDown); 
stage.addEventListener(KeyboardEvent.KEY_UP, keyIsUp); 
  
// Create object to store key states 
var keys:Dictionary = new Dictionary(true); 
  
function keyIsDown(e:KeyboardEvent):void 
{ 
    // Remember that the key was pressed 
    keys[e.keyCode] = true;     
  
    if (e.keyCode==Keyboard.LEFT || e.keyCode==Keyboard.RIGHT) 
    { 
        runningBoy.play(); 
    } 
} 
  
function keyIsUp(e:KeyboardEvent):void 
{ 
    // Remember that the key was released 
    keys[e.keyCode] = false; 
  
    for each (var value:Boolean in keys) 
          if ( value ) return; 
    runningBoy.stop(); 
} 
  
runningBoy.addEventListener(Event.ENTER_FRAME, handleMovement); 
runningBoy.stop(); 
  
var currentState:Number = runningBoy.scaleX; 
var speed:Number = 15; 
  
function handleMovement(e:Event):void 
{ 
    if (keys[Keyboard.RIGHT]) 
    { 
        e.currentTarget.x += speed; 
        e.currentTarget.scaleX = currentState;     
    } else if (keys[Keyboard.LEFT]) 
    { 
        e.currentTarget.x -= speed; 
        e.currentTarget.scaleX = -currentState; 
    } 
}

Visa grafik i full storlek
Filmklipp som samverkar med tangentbordet

När du klickar på knappen Remove tas filmklippet bort från visningslistan.

// Show or remove running boy 
showBtn.addEventListener (MouseEvent.CLICK,showIt); 
removeBtn.addEventListener (MouseEvent.CLICK,removeIt); 
 
function showIt (e:MouseEvent):void 
{ 
    addChild (runningBoy); 
} 
 
function removeIt(e:MouseEvent):void 
{ 
    if (contains(runningBoy)) removeChild(runningBoy); 
}

Trots att det tagits bort från visningslistan skickas händelsen Event.ENTER_FRAME från filmklippet. Filmklippet körs fortfarande men det återges inte. Du hanterar den här situationen korrekt genom avlyssna de rätta händelserna och ta bort händelseavlyssnare, för att på så sätt förhindra att processorkrävande kod kommer att köras:

// Listen to Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE 
runningBoy.addEventListener(Event.ADDED_TO_STAGE,activate); 
runningBoy.addEventListener(Event.REMOVED_FROM_STAGE,deactivate); 
 
function activate(e:Event):void 
{ 
    // Restart everything 
    e.currentTarget.addEventListener(Event.ENTER_FRAME,handleMovement); 
} 
 
function deactivate(e:Event):void 
{ 
    // Freeze the running boy - consumes fewer CPU resources when not shown 
    e.currentTarget.removeEventListener(Event.ENTER_FRAME,handleMovement); 
    e.currentTarget.stop(); 
}

När du klickar på knappen Show startas filmklippet om, händelsen Event.ENTER_FRAME avlyssnas igen och tangentbordet kan användas för att kontrollera filmklippet.

Obs! Om ett visningsobjekt tas bort från visningslistan är det inte säkert att objektet kommer att frysas om referensen anges som null sedan det tagits bort. Om skräpinsamlaren inte körs kommer objektet att fortsätta förbruka minne och processorkraft, trots att objektet inte längre visas. Om du vill vara säker på att objektet förbrukar minsta möjliga processorkraft, ska du se till att frysa det fullständigt när du tar bort det på visningslistan.

Från och med Flash Player 10 och AIR 1.5 finns även följande beteenden. Om spelhuvudet kommer till en tom bildruta fryses visningsobjektet automatiskt, även om du inte har implementerat något frysningsbeteende.

Frysningar också viktiga när du läser in fjärrinnehåll med klassen Loader. När du använde Loader-klassen i Flash Player 9 och AIT 1.0 var det nödvändigt att manuellt frysa innehållet genom att avlyssna händelsen Event.UNLOAD , som skickades av LoaderInfo-objektet. Varje händelse måste frysas manuellt, vilket inte alltid var en enkel uppgift. I Flash Player 10 och AIR 1.5 introducerades en viktig ny metod i klassen Loader, som kallas unloadAndStop() . Med denna metod kan du ta bort en SWF-fil, automatiskt frysa alla objekt i den inlästa SWF-filen och framtvinga körning av skräpinsamlaren.

I följande kod läses SWF-filen in och tas sedan bort med metoden unload() , vilket kräver mer bearbetning och manuell frysning:

var loader:Loader = new Loader(); 
 
loader.load ( new URLRequest ( "content.swf" ) ); 
 
addChild ( loader ); 
 
stage.addEventListener ( MouseEvent.CLICK, unloadSWF ); 
 
function unloadSWF ( e:MouseEvent ):void 
{ 
    // Unload the SWF file with no automatic object deactivation 
    // All deactivation must be processed manually 
    loader.unload(); 
}

Det bästa sättet är att använda metoden unloadAndStop() , som hanterar frysning internt och som framtvingar att skräpinsamlingsprocessen körs:

var loader:Loader = new Loader(); 
 
loader.load ( new URLRequest ( "content.swf" ) ); 
 
addChild ( loader ); 
 
stage.addEventListener ( MouseEvent.CLICK, unloadSWF ); 
 
function unloadSWF ( e:MouseEvent ):void 
{ 
    // Unload the SWF file with automatic object deactivation 
    // All deactivation is handled automatically 
    loader.unloadAndStop(); 
}

Följande åtgärder inträffar när metoden unloadAndStop() anropas:

  • Ljud stoppas.

  • Avlyssnare registrerade för SWF-filens huvudtidslinje tas bort.

  • Tidtagarobjekt stoppas.

  • Kringutrustning såsom kameror och mikrofoner frisläpps.

  • Alla filmklipp stoppas.

  • Utskick från Event.ENTER_FRAME , Event.FRAME_CONSTRUCTED , Event.EXIT_FRAME , Event.ACTIVATE och Event.DEACTIVATE stoppas.

Aktivera och inaktivera händelser

Använd händelserna Event.ACTIVATE och Event.DEACTIVATE för att identifiera bakgrundsinaktivitet och optimera programmet på rätt sätt.

Två händelser ( Event.ACTIVATE och Event.DEACTIVATE ) kan hjälpa dig att finjustera programmet så att det använder så få processorcykler som möjligt. Med hjälp av de här händelserna kan du avgöra när körningsmiljön får eller tappar fokus. Följaktligen kan du även optimera koden att reagera på förändringar i sammanhanget. Följande kod lyssnar på båda händelserna och ändrar dynamiskt bildrutefrekvensen till noll när programmet tappar fokus. Animeringen kan till exempel tappa fokus när användaren går till en annan flik eller placerar programmet i bakgrunden:

var originalFrameRate:uint = stage.frameRate; 
var standbyFrameRate:uint = 0; 
  
stage.addEventListener ( Event.ACTIVATE, onActivate ); 
stage.addEventListener ( Event.DEACTIVATE, onDeactivate ); 
  
function onActivate ( e:Event ):void 
{ 
    // restore original frame rate 
    stage.frameRate = originalFrameRate; 
} 
  
function onDeactivate ( e:Event ):void 
{ 
    // set frame rate to 0 
    stage.frameRate = standbyFrameRate; 
}

När programmet får fokus igen återställs bildrutefrekvensen till det ursprungliga värdet. I stället för att ändra bildrutefrekvensen dynamiskt kan du göra andra optimeringar, till exempel frysa och tina objekt.

Med händelserna activate och deactivate kan du implementera en mekanism, som liknar funktionen "Pausa och återuppta" i vissa mobilenheter och Netbooks.

Musinteraktion

Överväg när det är möjligt att inaktivera musinteraktioner.

När du använder ett interaktivt objekt, till exempel ett MovieClip- eller Sprite-objekt, körs den interna koden för att identifiera och hantera musinteraktion. Att identifiera musinteraktionen kan vara processorkrävande när många interaktiva objekt visas på skärmen och speciellt om de är överlappande. Ett enkelt sätt att undvika denna bearbetning är att inaktivera musinteraktionen för objekt som inte kräver musinteraktion. I följande kod visas exempel på hur du kan använda egenskaperna mouseEnabled och mouseChildren :

// Disable any mouse interaction with this InteractiveObject 
myInteractiveObject.mouseEnabled = false; 
const MAX_NUM:int = 10; 
  
// Create a container for the InteractiveObjects 
var container:Sprite = new Sprite(); 
  
for ( var i:int = 0; i< MAX_NUM; i++ ) 
{ 
    // Add InteractiveObject to the container 
    container.addChild( new Sprite() ); 
} 
  
// Disable any mouse interaction on all the children 
container.mouseChildren = false;

Överväg att inaktivera musinteraktion när det är möjligt, eftersom detta belastar processorn mindre, vilket i sin tur minskar batterianvändningen på mobilenheter.

Tidtagar- eller ENTER_FRAME-händelser

Välj antingen tidtagar- eller ENTER_FRAME -händelser beroende på innehållt som animeras.

Tidtagare är att föredra framför Event.ENTER_FRAME -händelser för innehåll som inte är animerat och som utförs under en lång tid.

I ActionScript 3.0 finns det två sätt att anropa en funktion med specifika intervaller. Det första sättet är att använda Event.ENTER_FRAME -händelsen som skickas med visningsobjekt (DisplayObject). Det andra sättet är att använda en tidtagare. ActionScript-utvecklare föredrar ofta ENTER_FRAME -händelsen. Händelsen ENTER_FRAME skickas för varje bildruta. Detta innebär att det intervall som används för att anropa funktionen är relaterad till den aktuella bildrutehastigheten. Bildrutehastigheten hämtas med egenskapen Stage.frameRate . Det kan emellertid i vissa fall vara bättre att använda en tidtagare än att använda händelsen ENTER_FRAME . Om du exempelvis inte använder en animering, men vill att koden ska anropas med specifika tidsintervall, kan det vara bättre att använda tidtagaren.

En tidtagare kan uppträda på liknande sätt som en ENTER_FRAME -händelse, men en händelse kan skickas utan att vara knuten till en bildrutehastighet. Detta kan medföra vissa optimeringsfördelar. Tänk dig exempelvis ett videospelarprogram. I detta fall behöver du inte använda en hög bildrutehastighet eftersom det endast är programkontrollerna som flyttas.

Obs! Videon påverkas inte av bildrutehastigheten eftersom videon inte är inbäddad på tidslinjen. Videon laddas i stället dynamiskt genom progressiv nedladdning eller direktuppspelning.

I detta exempel är bildrutehastigheten så låg som 10 bildrutor per sekund. Tidtagaren uppdaterar kontrollerna med en hastighet av en uppdatering per sekund. Den högre uppdateringshastigheten är möjlig genom metoden updateAfterEvent() som finns i objektet TimerEvent. Den här metoden medför att skärmen uppdateras varje gång som det finns behov av att en händelse skickas från tidtagaren. Detta illustreras med följande kod:

// Use a low frame rate for the application 
stage.frameRate = 10; 
  
// Choose one update per second 
var updateInterval:int = 1000; 
var myTimer:Timer = new Timer(updateInterval,0); 
  
myTimer.start(); 
myTimer.addEventListener( TimerEvent.TIMER, updateControls ); 
  
function updateControls( e:TimerEvent ):void 
{ 
    // Update controls here 
    // Force the controls to be updated on screen 
    e.updateAfterEvent(); 
}

När du anropar metoden updateAfterEvent() ändras inte bildrutehastighen. Det innebär bara att det innehåll som visas på skärmen, och som har ändrats, uppdateras. Tidslinjen forsätter att köras med 10 bildrutor per sekund. Tänk på att tidtagare och ENTER_FRAME -händelser inte fungerar helt perfekt på enheter med låg prestanda eller om händelsehanterarfunktionerna innehåller kod som kräver omfattande bearbetningar. Precis som för bildrutehastigheten för SWF-filer kan bildrutehastigheten för uppdateringen av tidtagaren variera i vissa situationer.

Minimera antalet Timer-objekt och registrerade enterFrame -hanterare i programmet.

För varje bildruta skickar körtidsmodulen en enterFrame -händelse till alla visningsobjekt i visningslistan. Trots att du kan registrera avlyssnare för enterFrame -händelsen med flera visningsobjekt innebär det att mer kod körs för varje bildruta. Överväg i stället att använda en centraliserad enterFrame -hanterare som verkställer all kod som ska köras i varje bildruta. Genom att centralisera koden är det enklare att hantera all kod som körs ofta.

Detsamma gäller när du använder timer-objekt, det finns risk för belastning när du skapar och skickar händelser från flera timer-objekt. Nedan följer några alternativa förslag om du måste aktivera olika åtgärder vid olika intervall:

  • Använd så få timer-objekt som möjligt och gruppera åtgärderna efter hur ofta de inträffar.

    Använd t.ex. en timer som är inställd att aktiveras var 100:e millisekund för åtgärder som utförs ofta. Använd en annan timer inställd att aktiveras var 2000:e millisekund för åtgärder som inte utförs så ofta eller som körs i bakgrunden.

  • Använd ett timer-objekt och låt åtgärderna aktiveras i multipler av timer-objektets intervall för delay -egenskapen.

    Anta t.ex. att du har vissa åtgärder som ska utföras var 100:e millisekund och andra som ska utföras var 200:e millisekund. I sådana fall ska du använda ett timer-objekt med ett delay -värde på 100 millisekunder. I händelsehanteraren timer ska du lägga till en villkorssats som bara kör 200 millisekundersåtgärderna varannan gång. Detta visas i följande exempel:

    var timer:Timer = new Timer(100); 
    timer.addEventListener(TimerEvent.Timer, timerHandler); 
    timer.start(); 
         
    var offCycle:Boolean = true; 
      
    function timerHandler(event:TimerEvent):void 
    { 
        // Do things that happen every 100 ms 
         
        if (!offCycle) 
        { 
            // Do things that happen every 200 ms 
        } 
         
        offCycle = !offCycle; 
    }
Stoppa Timer-objekt när de inte används.

Om timer -händelsehanteraren för ett Timer-objekt endast utför åtgärder under vissa förhållanden ska du anropa timerns stop() -metod när inga villkor är true.

Minimera antalet ändringar av visningsobjektets utseende som kan göra att skärmen ritas om i enterFrame -händelsen eller Timer-hanterarna.

För varje bildruta ritar återgivningsfasen om den del av scenen som ändrats i bildrutan. Om området som ritas om är stort eller om det är litet, men innehåller ett stort antal eller komplexa visningsobjekt, behöver körtidsmodulen mer tid för återgivningen. Använd funktionen “show redraw regions” i felsökningsversionen av Flash Player eller AIR när du vill testa hur mycket som måste ritas om.

Mer information om att förbättra prestandan för åtgärder som upprepas finns i följande artikel:

Interpoleringssyndromet

Minska processoranvändningen genom att begränsa användningen av interpolering vilket leder till minskade processorbearbetningar, minskat minnesutnyttjande och bättre batterikapacitet.

Designers och utvecklare som skapar innehåll för Flash på stationära datorer har en tendens att använda många interpoleringar i sina program. När du producerar innehåll för mobila enheter med låg prestanda ska du försöka minimera användningen av rörelseinterpoleringar. Genom att begränsa användningen körs innehållet snabbare på långsammare enheter.