Optimisez vos Applications avec le Multithreading

Optimisez vos Applications avec le Multithreading

Un Ordre Bien Défini

Le rôle d'un développeur est de définir les différentes instructions que votre ordinateur devra exécuter pour mener à bien un programme. Lors de son exécution, votre ordinateur lira chacune de ces instruction, et les exécutera les unes après les autres. Ce point est très important, car si une seule de ces instruction était erronée, tout votre programme serait impacté !

Je vous propose de voir cela au travers d'un exemple simple en apparence : La réalisation d'un mode multijoueur dans un jeu-vidéo. Notre objectif est de faire apparaître différents joueurs sur une même carte, chacun d'entre eux étant synchronisé avec les autres via une base de donnée sur un serveur. À chaque actualisation de l'écran, votre ordinateur donc devra effectuer les tâches suivantes :

• Afficher le décors du jeu.

• Déplacer le joueur principal.

• Afficher le joueur principal.

• Récupérer les positions des autres joueurs.

• Afficher ces autres joueurs.

• Et enfin, actualiser l'écran.

Je vous propose de schématiser ce fonctionnement, pour y voir plus clair.

Synchronous

En théorie, chacune de ces instructions se déclenche une fois que la précédente est terminée, et ainsi de suite pendant toute la durée de votre partie.

Un problème se pose toutefois avec un tel fonctionnement : Chacune de ces instructions prend un certain temps pour s'exécuter, et ce délai dépend de l'action que vous allez effectuer. Par exemple, une connexion au réseau pour y récupérer la position d'un joueur est beaucoup plus long que l'affichage de ce joueur à proprement parler.

Malheureusement, ni vous ni moi ne pouvez influencer ce délai d'exécution, car il est intrinsèquement lié à votre ordinateur.

Pendant ce temps, votre ordinateur ne peux rien faire, car il attends la fin de l'instruction en cours. Dans le cas d'un accès mémoire, le délai étant tellement court que ni vous ni votre ordinateur ne pourriez faire quoi que ce soit. Mais dans le cas d'une opération plus longue, comme une connexion à un serveur, il est possible que votre ordinateur se bloque pendant plusieurs centaines de millisecondes, ce qui est inconcevable si vous ne voulez pas faire fuir vos utilisateurs ! C'est ce qui s'appelle une exécution synchrone.

Paralléliser les instructions

Dans un jeux-vidéo, ou n'importe quel site web, la réactivité de votre application est un facteur déterminant si vous ne voulez pas frustrer vos utilisateurs. Vous ne pouvez donc pas accepter que votre ordinateur attende inutilement la fin d'une instruction sans rien faire d'autre. Comme le problème vient du fonctionnement à la chaine des instructions, nous allons essayer de les désynchroniser, pour qu'elles s'exécutent en parallèle, et non plus les unes à la suite des autres. En terme technique, cela s'appelle le multithreading.

Pour faire simple, un thread est une suite d'instructions que votre ordinateur va exécuter. Lorsque vous développez une application, celle-ci est automatiquement mise en place dans un thread unique, et fonctionne comme nous l'avons vu au dessus. Mais l'intérêt du multithreading est, comme son nom l'indique, de créer plusieurs threads, correspondant à plusieurs suites d'instructions. Nous allons donc créer un nouveau thread, et y mettre les opérations qui ralentissent notre thread principal.

Cela va nous permettre d'avoir un thread principal qui s'exécute rapidement, et un second thread plus lent, mais ne ralentissant pas le thread principal !

Asynchronous

Vous remarquerez que tous les threads ont un objectif commun : Mettre à jour l'écran. Pour y parvenir, il est nécessaire de leur donner un où plusieurs paramètres en lien avec cet objectif commun. Ici, nous pouvons utiliser un pointeur faisant référence à l'écran.

Ce paramètre est au coeur du multithreading. Il permet à chaque thread de fonctionner de son coté, et à la vitesse qu'il veut, et de mettre à jour l'écran dès qu'il a terminé son cycle.

Attention cependant : Chaque thread doit être indépendant du reste du programme. Par exemple, nous ne pouvons pas paralléliser la récupération de la position du joueur avec son affichage, car cette dernière implique de connaître sa position, et donc que l'instruction précédente soit terminée.

Pour vous aider à comprendre ce concept, je vous propose une petite comparaison avec la vie réelle. Imaginez un pizzaïolo qui fait cuire des pizzas une par une dans son four. Sa capacité de travail est délimitée par le temps de cuisson d'une pizza, et si le four venait à tomber en panne, toute sa production serait interrompue. Mais s'il décide d'investir dans un second four, il pourra faire deux services en même temps, et pourra continuer à travailler même en cas de panne de l'un des deux fours.

Si vous avez compris cet exemple, remplacez les pizzas par les instructions de votre programme, et les fours par les différents threads, et vous obtiendrez un parfait exemple du fonctionnement du multithreading !

Le Multithreading est Partout

Je vous ai donné un exemple de multithreading dans les jeux-vidéo, mais il faut savoir que son utilisation est omniprésente dans toute application moderne. Un exemple que vous avez probablement déjà utilisé sans même vous en rendre compte est l'utilisation de fonctions de callback en JavaScript.

Pour rappel, une fonction de callback est une fonction prédéterminée, qui est appelée en réponse à un événement donné. Pas plus loin que sur ce site, de nombreuses fonctions de callback sont définies. Regardez le bouton d'inscription à ma Newsletter, et plus exactement son code JavaScript :

 

$("#newsletterForm").submit(function(event) {
    event.preventDefault();

    alert("Merci de votre inscription !");
});

 

Il s'agit d'une fonction de callback, qui sera appelée lorsque le formulaire sera envoyé. Votre navigateur va exécuter cette fonction uniquement lorsque le formulaire sera envoyé, et donc que l'utilisateur aura saisi son adresse email. Ensuite, il suffira d'enregistrer cette adresse email, (Par exemple avec une requête AJAX) et remercier le visiteur pour son inscription.

Quel est le rapport entre les fonctions de callback et les threads ? Et bien celles-ci utilisent des threads pour programmer leur déclenchement. Sans thread, JavaScript devrait vérifier manuellement à chaque milliseconde l'état de chaque évènement, et éventuellement appeler les fonctions adéquates qui bloqueraient la navigation de l'utilisateur. Alors que là, votre navigateur va simplement créer un thread pour chaque fonction de callback, en spécifiant l'évènement demandé. Une fois celui-ci activé, la fonction sera exécutée directement depuis le thread, ce qui n'entravera pas le reste du programme.

Enfin, je vous ai parlé de threads logiciel, gérés par votre système d'exploitation. Mais depuis quelques années, nous assistons à l'apparition de processeur multicoeurs, qui permettent d'effectuer du multithreading de façon matérielle. Ce serait un peu compliqué à expliquer ici, mais cela permet à chaque coeur de votre processeur de superviser un thread différent, pour un fonctionnement globale encore plus rapide.

Le multithreading est un concept capital en programmation, et permet de créer différents fils d'exécution. Le résultat est un ensemble de sous-programmes qui fonctionnent en parallèle, afin d'optimiser le délai d'exécution de chaque opération. Ce principe a gagné en popularité au cours des dernières années, et est aujourd'hui extrêmement utilisé en informatique, de la programmation de jeux-vidéo en réseau, jusqu'au fonctionnement des sites internet modernes.

Written by Pythony on the 01/26/2020.

What did you think of this article ?

Other Articles

Optimize your Applications with Multithreading

Optimize your Applications with Multithreading

An application developed with a programming language is a sequence of instructions, executing one after the other. However, such an operation has a major disadvantage, which is the dependence of each instruction on the previous instructions. As a result, the slightest slowdown in one of these operations may impact your entire application

Read "Optimize your Applications with Multithreading"
Effectively Center in CSS with Flexbox

Effectively Center in CSS with Flexbox

Since the advent of CSS, centering an element has always been a problem for many developers. Many techniques were developed, but none of them allowed for reliable horizontal and vertical centering. Fortunately, the flexbox property greatly simplifies the task, allowing us to have an optimal rendering in a few lines

Read "Effectively Center in CSS with Flexbox"
Mastering the Terminal

Mastering the Terminal

Although not well known to the general public, the terminal is an essential element in the proper functioning of any operating system. Behind these lines, incomprehensible to most people, lies the precise operation of each action that your computer will be required to perform. From the simple creation of a file to the compilation of source code, the terminal hides many unsuspected resources

Read "Mastering the Terminal"