Mathieu Agopian : Latence et boucle de rétroaction

Latence

La latence en informatique est un délai minimum de transmission. C'est un des principaux ennemis de la performance notamment dans le domaine du web.

Un site web est généralement composé de multiples fichiers statiques (css, javascript, images et icônes en tout genre). Pour afficher la totalité d'une page, il faut donc faire de multiples requêtes au serveur, chacune prenant un certain temps de traitement, à quoi on rajoute la latence (le temps de transfert sur le réseau).

On imagine facilement l'impact d'une forte latence lorsqu'il faut effectuer plusieurs dizaines voire centaines de requêtes. Même si la latence n'est que de 10ms, si on multiple ça par 100, on atteint déjà une seconde.

Prenons un autre exemple : il n'est pas rare d'avoir des pages nécessitant des dizaines (des centaines, voire des milliers ?) de requêtes SQL à une base de données. Là encore, il faut multiplier ce nombre de requête par le temps de traitement par la base de données, mais aussi par la latence.

Étant donné la difficulté de réduire la latence, l'optimisation de la performance passe par le réduction du nombre de requêtes : on fait des bundles pour les fichiers statiques (on regroupe toutes les CSS ou les fichiers javascript, on crée des image map pour les icônes), on fait usage du JOIN pour les requêtes SQL...

Boucle de rétroaction

La boucle de rétroaction (appelée « feedback loop » en anglais) permet de raffiner un système afin d'arriver à un équilibre, à un objectif.

Une boucle de rétroaction basée sur des mesures de position permettra à robot d'atteindre la position souhaitée : la vitesse et la direction seront adaptées en fonction de la distance à l'objectif.

Plus la boucle de rétroaction sera longue, plus l'équilibre sera long a atteindre. En effet, si la mesure de position ne se fait qu'une fois toutes les 10 secondes, soit le robot devra se déplacer très lentement, soit faire de nombreux aller-retours.

Le rapport ?

En tant qu'informaticien, il nous arrive régulièrement d'avoir à raffiner un bout de code en fonction de différents paramètres : l'expression du besoin, la rapidité d'exécution, l'occupation mémoire...

Et ce raffinage se fait par le biais d'une boucle de rétroaction qui peut prendre différentes formes :

Si la latence s'invite dans ce mécanisme, on se retrouve dans la même situation que le robot qui doit atteindre une position, mais qui n'a de retour sur sa position que rarement. Soit on avance vite et on risque les aller-retours (comprendre : réécriture du code), soit on avance lentement.

Dans tous les cas, c'est un cauchemar.

Voici quelques exemples de latence :

Un exemple concret

Avec mon collègue David nous nous sommes chargés de la résolution d'un ticket pour le projet AMO.

Afin de pouvoir présenter des graphiques d'utilisation/téléchargement des extensions à leur auteur (comme pour Firebug), toutes les requêtes de téléchargement et de demande de mise à jour sont enregistrées et stockées dans une base de données « big data » (pour les curieux : c'est stocké dans Hadoop et récupéré par le biais de Hive). On parle de plus d'un milliard de requête par jour, toutes requêtes confondues.

Ce qui nous a d'abord paru simple et rapide à implémenter, s'est transformé en deux semaines de sprint (et n'est pas encore terminé).

Nous avons subit et fait partie des différentes formes de latences listées ci-dessus :

La solution

Diminuer la latence dans la boucle de rétroaction, par tous les moyens possibles.

De la même manière qu'il arrive régulièrement de lancer un interpréteur Python (ou un ipdb ;) pour bidouiller et expérimenter avec un petit bout de code et avoir des retours immédiats, il faut tout faire pour accélérer la boucle de rétroaction.

Et à ma plus grande honte, ne pas avoir de tests unitaires a été un boulet supplémentaire : lancer un post-traitement pour s'apercevoir 15 minutes plus tard qu'on a oublié une virgule dans le code...