top of page

4. Minimiser la consommation CPU

Puisque un affichage de 25 images par seconde suffit et que l’affichage se produit à chaque tour de boucle, l’idée est de ralentir cette boucle. Nous allons donc rajouter un délai dans la boucle. Mais comme la durée d’exécution est variable en fonction des instructions (les instructions ne sont pas toujours les mêmes selon le traitement des évènements), plutôt que de rajouter un simple délai fixe, nous allons calculer ce délai pour que la boucle ait une durée constante.

Pour ce faire nous allons mesurer le temps d’exécution du programme et rajouter un délai pour obtenir une durée constante, par exemple de 40ms (25 images/s).

Dans notre organigramme, après avoir déroulé toutes les instructions, on appelle SDL_Delay() qui va mettre le programme en PAUSE : pendant ce temps la consommation CPU est nulle, le processeur est disponible pour un autre programme (ou pour d’autres threads de notre programme).

La modification consiste a rajouter une fonction GesFrame() qui va gérer cette régulation de la boucle , on obtient alors un gros avantage :

Les instructions de la boucle (en particulier Affichage() ) sont répétées avec une période fixe ce qui permet de faire très facilement des incrémentations en fonction du temps pour des déplacements de sprites ou des animations.

Cette fonction sert à rajouter un délai à la suite de l’exécution des premières instructions de la boucle principale (lignes 77 à 85) de façon à obtenir une durée constante pour l’exécution totale de la boucle (lignes 77 à 86). Pendant ce délai, le programme ne fait rien : il est en pause, on économise le CPU.

Voici un exemple classique :

Lorsque l’on arrive à la ligne 244 on fait la différence entre le temps actuel (qui vient d’être pris en ligne 243) et le temps de début de boucle : tempsPrecedent (en fait c’est le temps de la fin de la boucle précédente pris en ligne 250 ; cette instruction est la dernière de la boucle principale).

Si cette différence est inférieure à la durée de boucle choisie (t_frame) : on rajoute un délai pour obtenir cette durée.

Si cette différence est déjà supérieure (ce qui arrive rarement) : on ne fait rien.

On obtient une exécution à fréquence fixe (période = t_frame) des 2 fonctions  Actualisation()  et Affichage()  ce qui est le but recherché. En pratique, pour avoir un affichage fluide, on ne descendra pas en dessous de 25 images/s. soit une période t_frame = 40ms.    ( #define t_frame 40 )

Pour le vérifier rajouter dans Affichage()  à la fin l’instruction suivante :

printf("Instant fin d'affichage (ms) : %i \n",SDL_GetTicks());

Voilà, nous avons définit la structure d’un programme regroupée en un minimum de fonctions :

Elle contient deux boucles :

  • une boucle (principale) qui tourne tant que l’on ne veut pas quitter le programme

  • une boucle interne qui tourne tant qu’il y a des évènements (du passé) à traiter

 

Cette structure peut être employée pour tous vos programmes, il suffit de personnaliser les fonctions.

 

La fonction Actualisation() dépend du programme : mise à jour des variables, de la position des sprites dans un jeu, etc…

La fonction Affichage() va contenir les Blits  et se termine par un SDL_Flip() unique dans le programme.

La fonction switchEvent() dépend aussi du programme : c’est elle qui assure les traitements en fonction des évènements.

Son squelette a toujours la même structure :

Et voici la fonction gesMotion() dans cet exemple :

Cette architecture est classique et convient pour la majorité des programmes cependant elle n'est pas optimale :

Si maintenant vous bougez rapidement la souris : vous remarquerez que l’image ne suit plus aussi bien le curseur de la souris.

C’est normal, pendant le temps où le programme est en pause tous les évènements de mouvements souris ne sont pas traités : ils seront dépilés au prochain tour de la boucle principale.

 

Du coup l’affichage est actualisé sur des positions qui sont déjà bien écartées les unes des autres (regardez les valeurs de x) cela se produit uniquement environ toutes les 40ms.

 

Nous allons voir dans la suite une autre solution plus performante puis proposer une architecture optimale.

    < Page précédente                                                                                                    Sommaire                                                                 > Page suivante

bottom of page