En matière d’optimisation, il est également impératif de tenir compte de l’utilisation de l’unité centrale. L’optimisation du traitement par l’unité centrale améliore les performances et, par conséquent, la durée de vie de la batterie des périphériques mobiles.
Améliorations de Flash Player 10.1 liées à l’utilisation de l’unité centrale
Flash Player 10.1 propose deux nouvelles fonctions qui permettent d’économiser la puissance de traitement de l’unité centrale, à savoir la mise en pause et la reprise du contenu SWF lorsque ce dernier sort de l’écran, et la limitation du nombre d’occurrences de Flash Player sur une page.
Pause, ralentissement et reprise
Remarque :
la fonction de pause, ralentissement et reprise n’est pas disponible sur les applications Adobe® AIR®.
Pour optimiser l’utilisation de l’unité centrale et de la batterie, Flash Player 10.1 propose une nouvelle fonction relative aux occurrences inactives. Cette fonction permet de limiter l’utilisation de l’unité centrale en mettant en pause et en reprenant le fichier SWF lorsque le contenu sort de l’écran et y revient. Grâce à cette fonction, Flash Player libère autant de mémoire que possible en supprimant tout objet pouvant être recréé lorsque la lecture du contenu reprend. Est considéré comme hors écran, tout contenu qui est totalement sorti de l’écran.
Deux cas de figure entraînent la sortie de l’écran du contenu SWF :
-
L’utilisateur fait défiler la page et le contenu SWF sort de l’écran.
Dans ce cas, tout contenu audio ou vidéo en cours de lecture continue de s’exécuter mais le rendu est interrompu. Si aucun contenu audio ou vidéo n’est en cours de lecture, pour parer à toute mise en pause de la lecture ou de l’exécution d’ActionScript, définissez le paramètre HTML
hasPriority
sur true. Souvenez-vous cependant que, lorsque le contenu SWF est hors écran ou masqué, son rendu est mis en pause, quelle que soit la valeur du paramètre
hasPriority
.
-
L’utilisateur ouvre un onglet dans le navigateur, faisant passer à l’arrière-plan le contenu SWF.
Dans ce cas, quelle que soit la valeur de la balise HTML
hasPriority
, le contenu SWF est
ralenti
ou réduit de 2 à 8 ips. La lecture audio et vidéo est arrêtée et aucun rendu n’est traité à moins que le contenu SWF ne soit à nouveau visible.
Pour Flash Player 11.2 et les versions ultérieures exécutées sur des navigateurs Windows et Mac, vous pouvez utiliser l’événement ThrottleEvent dans votre application. Flash Player distribue un événement ThrottleEvent lorsqu’il interrompt, ralenti ou reprend la lecture.
L’événement ThrottleEvent est un événement de diffusion, c’est-à-dire qu’il est distribué par tous les objets EventDispatcher disposant d’un écouteur de cet événement. Pour plus d’informations sur les événements de diffusion, voir la classe
DisplayObject
.
Gestion des occurrences
Remarque :
la fonction de gestion des occurrences ne s’applique pas aux applications Adobe® AIR®.
Utilisez le paramètre HTML
hasPriority
pour retarder le chargement des fichiers SWF hors écran.
Flash Player 10.1 propose un nouveau paramètre HTML,
hasPriority
:
<param name="hasPriority" value="true" />
Cette fonction limite le nombre d’occurrences de Flash Player démarrées sur une page, ce qui permet de conserver les ressources de l’unité centrale et de la batterie. Il s’agit d’attribuer une priorité spécifique au contenu SWF, de sorte qu’un certain contenu soit prioritaire sur une page. Prenons un exemple simple : un utilisateur explore un site Web dont la page d’index héberge trois fichiers SWF différents. Le premier est entièrement visible, le deuxième l’est partiellement et le dernier est hors écran et ne peut être atteint que par défilement. Les deux premières animations démarrent normalement mais la troisième est différée jusqu’à ce qu’elle devienne visible. C’est le comportement par défaut lorsque le paramètre
hasPriority
est absent ou défini sur
false
. Pour s’assurer du démarrage d’un fichier SWF, même s’il est hors écran, définissez le paramètre
hasPriority
sur
true
. Toutefois, quelle que soit la valeur du paramètre
hasPriority
, le rendu d’un fichier SWF qui n’est pas visible pour l’utilisateur est toujours mis en pause.
Remarque :
si les ressources de l’unité centrale sont insuffisantes, les occurrences de Flash Player ne démarrent plus automatiquement, même si le paramètre
hasPriority
correspond à
true
. Les nouvelles occurrences éventuellement créées par le biais de JavaScript après le chargement de la page ne tiennent pas compte de l’indicateur
hasPriority
. Tout contenu de 1 x 1 ou 0 x 0 pixel démarre, empêchant le report du lancement des fichiers SWF d’aide si le webmestre omet l’indicateur
hasPriority
. Il est cependant toujours possible de démarrer les fichiers SWF en cliquant dessus. Ce comportement est appelé « cliquer pour lire ».
Le schéma ci-dessous illustre l’effet de la définition du paramètre
hasPriority
sur différentes valeurs :
Effets de différentes valeurs affectées au paramètre hasPriority
Effets de différentes valeurs affectées au paramètre hasPriority
Mode veille
Flash Player 10.1 et AIR 2.5 offrent, sur les périphériques mobiles, une nouvelle fonction qui permet d’économiser la puissance de traitement et, par conséquent, de prolonger la durée de vie des batteries. Cette fonction est liée à la fonction de rétroéclairage des périphériques mobiles. Par exemple, si un utilisateur exécutant une application mobile est interrompu et cesse d’utiliser son périphérique, le moteur d’exécution détecte le passage en mode veille du rétroéclairage. Il réduit alors la cadence à 4 images par seconde et interrompt le rendu. Pour les applications AIR, le mode veille est également activé lorsque l’application passe en arrière-plan.
Le code ActionScript continue à s’exécuter en mode veille, ce qui revient à définir la propriété
Stage.frameRate
sur 4 images par seconde. Cependant comme l’étape de rendu est omise, l’utilisateur ne se rend pas compte de la cadence. Le choix s’est arrêté sur 4 images par seconde, et non sur zéro, pour que toutes les connexions (NetStream, Socket et NetConnection) restent ouvertes. Une cadence nulle entraînerait la fermeture de toutes les connexions ouvertes. De même, la fréquence d’actualisation est définie sur 250 ms (4 images par seconde), car c’est celle qu’utilisent de nombreux fabricants de périphériques. Cette valeur permet donc d’adapter la cadence du moteur d’exécution au réglage du périphérique.
Remarque :
lorsque le moteur d’exécution est en mode veille, la propriété
Stage.frameRate
renvoie la cadence du fichier SWF d’origine, et non 4 ips.
Lors de la réactivation du rétroéclairage, le rendu reprend et la cadence originale est rétablie. Imaginons qu’utilisateur écoute de la musique sur un lecteur multimédia. Si l’écran passe en mode veille, le comportement du moteur d’exécution dépend du type de contenu en cours de lecture. Voici une liste des divers cas de figure possibles et des comportements correspondants du moteur d’exécution :
-
Le rétroéclairage passe en mode veille et le contenu en cours de lecture est de type non-A/V : le rendu est mis en pause et la cadence est définie sur 4 images par seconde.
-
Le rétroéclairage passe en mode veille et le contenu en cours de lecture est de type A/V : le moteur d’exécution empêche la mise en veille du rétroéclairage et rien ne change pour l’utilisateur.
-
Le rétroéclairage quitte le mode veille : le moteur d’exécution définit la cadence sur le paramètre correspondant du fichier SWF original et reprend le rendu.
-
Flash Player est mis en pause pendant la lecture de contenu A/V : Flash Player rétablit le comportement système par défaut du rétroéclairage, car la lecture du contenu A/V est interrompue.
-
Le périphérique mobile reçoit un appel pendant la lecture de contenu A/V : le rendu est mis en pause et la cadence est définie sur 4 images par seconde.
-
Le mode veille du rétroéclairage est désactivé sur un périphérique mobile : le moteur d’exécution se comporte normalement.
Lorsque le rétroéclairage est mis en veille, le rendu est mis en pause et la cadence ralentit. Si bénéfique soit-elle sur la charge de l’unité centrale, cette fonction ne permet cependant pas de créer une pause réelle, comme dans une application de jeu.
Remarque :
aucun événement ActionScript n’est distribué lorsque le moteur d’exécution passe en mode veille ou le quitte.
Figement et libération d’objets
Pour figer et libérer des objets correctement, utilisez les événements
REMOVED_FROM_STAGE
et
ADDED_TO_STAGE
.
Pour optimiser le code, figez et libérez systématiquement les objets. Il est important d’effectuer ces opérations pour tous les objets, et plus particulièrement les objets d’affichage. Même s’ils ne figurent plus sur la liste d’affichage et sont en attente de nettoyage, les objets d’affichage sont toujours susceptibles de solliciter fortement l’unité centrale. Il se peut, par exemple, qu’ils continuent d’utiliser Event.ENTER_FRAME. Il est donc impératif de figer et de libérer correctement les objets à l’aide des événements
Event.REMOVED_FROM_STAGE
et
Event.ADDED_TO_STAGE
. L’exemple suivant illustre un clip qui s’exécute sur la scène et communique avec le clavier :
// 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;
}
}
Lorsque l’utilisateur clique sur le bouton Remove (Supprimer), le clip est effacé de la liste d’affichage :
// 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);
}
Bien que supprimé de la liste d’affichage, le clip distribue toujours l’événement
Event.ENTER_FRAME
. Son exécution se poursuit même si son rendu est interrompu. Pour gérer correctement cette situation, écoutez les événements appropriés et supprimez des écouteurs d’événements, afin d’éviter l’exécution de code sollicitant fortement l’unité centrale :
// 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();
}
Lorsque l’utilisateur appuie sur le bouton Show (Afficher), le clip redémarre, écoute à nouveau les événements
Event.ENTER_FRAME
et le clavier le contrôle correctement.
Remarque :
si un objet d’affichage est supprimé de la liste d’affichage, il ne suffit pas, pour le figer, de définir sa référence sur
null
après sa suppression. Si le nettoyeur de mémoire ne s’exécute pas, l’objet continue de solliciter la mémoire et l’unité centrale même s’il n’est plus affiché. Pour vous assurer que l’objet sollicite le moins possible l’unité centrale, veillez à le figer complètement lors de sa suppression de la liste d’affichage.
A partir de Flash Player 10 et AIR 1.5, le comportement suivant se produit également. Si la tête de lecture atteint une image vide, l’objet d’affichage est automatiquement figé même si vous n’avez pas implémenté un tel comportement.
Le concept de figement est également important lors du chargement de contenu à distance à l’aide de la classe Loader. Lorsque vous utilisiez cette classe dans Flash Player 9 et AIR 1.0, il était nécessaire de figer manuellement le contenu en écoutant l’événement
Event.UNLOAD
distribué par l’objet LoaderInfo. Il fallait donc figer manuellement tous les objets, une tâche laborieuse. La nouvelle méthode
unloadAndStop()
de la classe Loader constitue une nouveauté importante dans Flash Player 10 et AIR 1.5. Elle permet en effet de décharger un fichier SWF, de figer automatiquement chaque objet du fichier et d’imposer l’exécution du nettoyeur de mémoire.
Dans le code ci-après, le fichier SWF est chargé puis déchargé par le biais de la méthode
unload()
, qui est gourmande en ressources de traitement et exige un figement manuel :
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();
}
Il est préférable d’utiliser la méthode
unloadAndStop()
, qui gère le figement en natif et impose l’exécution du nettoyeur de mémoire :
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();
}
L’appel de la méthode
unloadAndStop()
entraîne les actions suivantes :
-
Les sons sont arrêtés.
-
Les écouteurs enregistrés sur le scénario principal du fichier SWF sont supprimés.
-
Les objets Timer sont arrêtés.
-
Les périphériques matériels (caméras, microphones, etc.) sont libérés.
-
Tous les clips sont arrêtés.
-
Les événements
Event.ENTER_FRAME
,
Event.FRAME_CONSTRUCTED
,
Event.EXIT_FRAME
,
Event.ACTIVATE
et
Event.DEACTIVATE
ne sont plus distribués.
Evénements activate et deactivate
Utilisez les événements
Event.ACTIVATE
et
Event.DEACTIVATE
pour détecter l’inactivité de l’arrière-plan et optimiser votre application.
Deux événements (
Event.ACTIVATE
et
Event.DEACTIVATE
) peuvent vous aider à optimiser votre application de façon à ce qu’elle consomme le moins de ressources de l’unité centrale possible. Ces événements permettent de savoir quand le moteur d’exécution possède ou perd le focus. Il est ainsi possible d’optimiser le code de telle sorte qu’il réagisse aux changements de contexte. Le code suivant écoute ces deux événements et définit dynamiquement la cadence sur zéro lorsque l’application perd le focus. Par exemple, l’animation peut perdre le focus lorsque l’utilisateur sélectionne un autre onglet ou fait passer l’application en arrière-plan :
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;
}
Lorsque l’application retrouve le focus, la cadence reprend sa valeur d’origine. Plutôt que de modifier dynamiquement la cadence, vous pouvez effectuer d’autres optimisations, par exemple le figement ou la libération d’objets.
Les événements activate et deactivate permettent de mettre en oeuvre un mécanisme similaire à la fonction « pause et reprise » parfois disponible sur les périphériques mobiles et les ordinateurs miniportables.
Interactions de la souris
Dans la mesure du possible, désactivez les interactions de la souris.
Lors de l’utilisation d’un objet interactif, tel qu’un objet MovieClip ou Sprite, le moteur d’exécution exécute du code natif pour détecter et gérer les interactions de la souris. Lorsque de nombreux objets interactifs sont affichés, ce processus de détection peut solliciter fortement l’unité centrale, surtout si les objets se chevauchent. Pour parer à cet écueil, le plus simple consiste à désactiver les interactions de la souris sur les objets pour lesquels elles ne sont pas nécessaires. Le code suivant illustre l’utilisation des propriétés
mouseEnabled
et
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;
Lorsque cela est possible, désactivez les interactions de la souris : votre application fait alors une utilisation moins intensive de l’unité centrale, d’où une consommation réduite de la batterie sur les périphériques mobiles.
Minuteurs et événements ENTER_FRAME
Optez pour des minuteurs ou des événements
ENTER_FRAME
, selon que le contenu est animé ou non.
Lorsque le contenu n’est pas animé et s’exécute pendant une longue période, les minuteurs sont préférables aux événements
Event.ENTER_FRAME
.
Dans ActionScript 3.0, il est possible d’appeler une fonction à intervalles réguliers de deux manières. La première repose sur l’utilisation de l’événement
Event.ENTER_FRAME
distribué par les objets d’affichage (DisplayObject). La seconde est fondée sur l’utilisation d’un minuteur. Les développeurs ActionScript privilégient fréquemment l’utilisation de l’événement
ENTER_FRAME
. L’événement
ENTER_FRAME
est distribué sur chaque image. La fréquence d’appel de la fonction est donc relative à la cadence en cours. La cadence est accessible par le biais de la propriété
Stage.frameRate
. Il est cependant préférable, dans certains cas, de faire appel à un minuteur plutôt qu’à l’événement
ENTER_FRAME
. C’est le cas, par exemple, si vous ne définissez pas d’animation mais souhaitez appeler le code à fréquence régulière.
Un minuteur peut se comporter de manière similaire à un événement
ENTER_FRAME
, mais il permet de distribuer un événement sans être tributaire de la cadence. Ce comportement peut permettre une optimisation sensible. Prenons l’exemple d’un lecteur vidéo. Dans ce cas, une cadence élevée n’est pas indispensable, car seuls les contrôles de l’application se déplacent.
Remarque :
la cadence n’affecte pas la vidéo parce que celle-ci n’est pas intégrée au scénario. La vidéo est chargée dynamiquement par téléchargement progressif ou diffusion en continu.
Dans cet exemple, la cadence est réglée sur une valeur faible, 10 ips. Le minuteur met à jour les contrôles, à raison de une mise à jour par seconde. Le taux de mise à jour plus élevé est possible grâce à la méthode
updateAfterEvent()
, qui est disponible sur l’objet TimerEvent. Cette méthode impose la mise à jour de l’écran chaque fois que le minuteur distribue un événement, si besoin est. Le code suivant illustre ce concept :
// 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();
}
L’appel de la méthode
updateAfterEvent()
ne modifie pas la cadence. Cette méthode force simplement le moteur d’exécution à mettre à jour le contenu de l’écran qui a changé. Le scénario s’exécute toujours à 10 ips. Souvenez-vous cependant que les minuteurs et les événements
ENTER_FRAME
ne sont pas d’une précision à toute épreuve sur les périphériques dont les performances sont médiocres ou si les fonctions de gestionnaire d’événement contiennent du code exigeant un traitement intensif. A l’instar de la cadence des fichiers SWF, le taux de mise à jour du minuteur peut varier en fonction des circonstances.
Définissez un minimum d’objets Timer et de gestionnaires
enterFrame
enregistrés dans l’application.
Sur chaque image, le moteur d’exécution distribue un événement
enterFrame
à chaque objet figurant sur sa liste d’affichage. Vous pouvez enregistrer des écouteurs pour l’événement
enterFrame
sur plusieurs objets d’affichage mais cela signifie que le volume de code exécuté sur chaque image est plus élevé. Envisagez plutôt de définir un gestionnaire
enterFrame
centralisé unique qui exécute tout le code destiné à chaque image. En centralisant ce code, il est plus facile de gérer tout le code qui s’exécute fréquemment.
De même, si vous utilisez plusieurs objets Timer, la création et la distribution des événements correspondants se traduisent par une augmentation du temps système nécessaire. Si vous devez déclencher différentes opérations à différents intervalles, nous vous suggérons de procéder comme suit, au choix :
-
Utilisez un minimum d’objets Timer et regroupez les opérations en fonction de leur fréquence d’exécution..
Définissez, par exemple, un objet Timer se déclenchant toutes les 100 millisecondes pour les opérations fréquentes et un autre, réglé sur 2000 millisecondes, pour les opérations moins fréquentes ou exécutées en arrière-plan.
-
Utilisez un seul objet Timer et déclenchez les opérations à des fréquences consistant en des multiples de la propriété
delay
de l’objet.
Supposons, par exemple, que vous souhaitiez exécuter certaines opérations toutes les 100 millisecondes et d’autres toutes les 200 millisecondes. A cet effet, créez un seul objet Timer et définissez sa propriété
delay
sur 100 millisecondes. Dans le gestionnaire d’événement
timer
, ajoutez une instruction conditionnelle qui exécute une fois sur deux seulement les opérations à répéter toutes les 200 millisecondes. L’exemple suivant illustre cette technique :
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;
}
Arrêtez les objets Timer lorsqu’ils ne sont pas utilisés.
Si le gestionnaire d’événement
timer
d’un objet Timer n’exécute des opérations que dans certaines conditions, appelez la méthode
stop()
de l’objet lorsqu’aucune des conditions n’est vérifiée.
Dans un événement
enterFrame
ou des gestionnaires Timer, évitez autant que possible d’apporter à l’apparence de l’objet d’affichage des modifications entraînant l’actualisation de l’écran.
Sur chaque image, la phase de rendu retrace la zone de la scène qui a changé pendant l’image. Si cette zone est de grande taille ou si elle est petite mais contient des objets d’affichage nombreux ou complexes, le temps nécessaire pour le rendu augmente. La fonction « Afficher les zones de retraçage » de la version de débogage de Flash Player ou AIR permet de déterminer la quantité de retraçage nécessaire.
Pour plus d’informations sur l’amélioration des performances des actions répétées, voir l’article suivant :
Interpolations
Evitez d’utiliser des interpolations pour économiser la puissance de traitement de l’unité centrale, la mémoire et la vie de la batterie.
Les concepteurs et développeurs qui produisent du contenu pour Flash sur le bureau ont tendance à être grands consommateurs d’interpolations de mouvement dans leurs applications. Lorsque vous créez du contenu destiné à des périphériques mobiles, limitez autant que possible l’utilisation des interpolations de mouvement afin que le contenu s’exécute plus rapidement sur les périphériques bas de gamme.
|
|
|