|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- title: Latence et boucle de rétroaction
- url: http://mathieu.agopian.info/blog/latence-et-boucle-de-retroaction.html
- hash_url: f1ed7d7dff2ed14214bdf7a25dde1d74
-
- <h2>Latence</h2>
- <p>La <a class="reference external" href="http://fr.wikipedia.org/wiki/Latence_%28informatique%29">latence</a> en informatique est un délai minimum de transmission. C'est un des
- principaux ennemis de la performance notamment dans le domaine du web.</p>
- <p>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).</p>
- <p>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.</p>
- <p>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.</p>
- <p>É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
- <em>bundles</em> pour les fichiers statiques (on regroupe toutes les CSS ou les
- fichiers javascript, on crée des <em>image map</em> pour les icônes), on fait usage du
- <em>JOIN</em> pour les requêtes SQL...</p>
- </div>
- <div class="section" id="boucle-de-retroaction">
- <h2>Boucle de rétroaction</h2>
- <p>La <a class="reference external" href="http://fr.wikipedia.org/wiki/Boucle_de_r%C3%A9troaction">boucle de rétroaction</a> (appelée « feedback loop » en anglais) permet de
- raffiner un système afin d'arriver à un équilibre, à un objectif.</p>
- <p>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.</p>
- <p>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.</p>
- </div>
- <div class="section" id="le-rapport">
- <h2>Le rapport ?</h2>
- <p>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...</p>
- <p>Et ce raffinage se fait par le biais d'une boucle de rétroaction qui peut
- prendre différentes formes :</p>
- <ul class="simple">
- <li>des tests automatisés (test unitaires ou fonctionnels, TDD...)</li>
- <li>des tests manuels</li>
- <li>des simulations</li>
- <li>des aller-retours avec l'utilisateur final, le décideur, ...</li>
- </ul>
- <p>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.</p>
- <p>Dans tous les cas, c'est un cauchemar.</p>
- <p>Voici quelques exemples de latence :</p>
- <ul class="simple">
- <li>besoin mal exprimé ou mal compris (la mesure de position n'est pas fiable)</li>
- <li>périmètre fonctionnel qui change (la position finale du robot change en cours
- de route)</li>
- <li>grand nombre d'aller-retours avec l'utilisateur final/décideur (nécessité de
- faire un très grand nombre de mesures de position)</li>
- <li>retours de l'utilisateur final/décideur très lents (mesure de position très
- rare)</li>
- <li>dialogue avec une API/base de données/système distant/... très lent (chaque
- mesure de position demande de très longs traitements)</li>
- <li>peu de confiance dans les résultats (nécessité de refaire plusieurs fois les
- mesures ou de les retraiter)</li>
- </ul>
- </div>
- <div class="section" id="un-exemple-concret">
- <h2>Un exemple concret</h2>
- <p>Avec mon collègue <a class="reference external" href="https://larlet.fr/david/">David</a> nous nous sommes chargés de la résolution d'un ticket
- pour le projet <a class="reference external" href="https://addons.mozilla.org">AMO</a>.</p>
- <p>Afin de pouvoir présenter des graphiques d'utilisation/téléchargement des
- extensions à leur auteur (comme pour <a class="reference external" href="https://addons.mozilla.org/en-US/firefox/addon/firebug/statistics/?last=30">Firebug</a>), 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 <a class="reference external" href="http://hadoop.apache.org/">Hadoop</a>
- et récupéré par le biais de <a class="reference external" href="https://hive.apache.org/">Hive</a>). On parle de plus d'un milliard de requête
- par jour, toutes requêtes confondues.</p>
- <p>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é).</p>
- <p>Nous avons subit et fait partie des différentes formes de latences listées
- ci-dessus :</p>
- <ul class="simple">
- <li>besoin mal exprimé ou mal compris : la répartition des tâches entre nous et
- notre interlocuteur a changé plusieurs fois. Par ailleurs nous n'avions
- aucune connaissance du système avant de nous y attaquer.</li>
- <li>périmètre fonctionnel qui change : malheureusement, arrivé au bout de la
- première semaine de sprint, nous avons appris qu'il nous fallait refaire la
- moitié de notre travail différemment suite à des contraintes non prévues.</li>
- <li>grand nombre d'aller-retours avec l'utilisateur final/décideur : à l'heure de
- l'écriture de ce billet, nous en sommes à 54 commentaires sur le ticket.</li>
- <li>retours de l'utilisateur final/décideur très lent : nous travaillons en
- France, et notre interlocuteur sur la côte ouest des USA (-9h). Il est
- fréquent d'avoir besoin d'attendre le lendemain pour avoir une réponse, dans
- un sens ou dans l'autre.</li>
- <li>dialogue avec un système distant très lent : de par le nombre de données à
- traiter, chaque requête à Hive (au nombre de 6) prend en moyenne 15 minutes,
- et la taille des données à télécharger varie entre 500Mo et 1.6Go.</li>
- <li>peu de confiance dans les résultats : nous essayions de mettre au point les
- requêtes Hive à exécuter, et par le même temps, le post-traitement de ces
- requêtes, pour coller au plus proche aux statistiques et graphiques attendus.
- Jouer sur deux paramètres en même temps est déjà malaisé en temps normal,
- mais là il nous était de plus très laborieux de confronter nos résultats avec
- ceux de la production.</li>
- </ul>
- </div>
- <div class="section" id="la-solution">
- <h2>La solution</h2>
- <p>Diminuer la latence dans la boucle de rétroaction, par tous les moyens
- possibles.</p>
- <p>De la même manière qu'il arrive régulièrement de lancer un interpréteur Python
- (ou un <em>ipdb</em> ;) 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.</p>
- <ul class="simple">
- <li>ça paraît évident, mais connaître précisément le besoin et le contexte avant
- de se lancer est primordial. Nous avons facilement perdu deux à trois jours à
- cause de ça, en début de sprint, avec notre envie d'avancer rapidement (et de
- passer à quelque chose de plus fun ;)</li>
- <li>périmètre fonctionnel qui change : difficile de le prévoir ou de l'éviter,
- mais je pense qu'en ayant une boucle de rétroaction plus courte, nous aurions
- eu des résultats plus rapidement, et aurions alors plus rapidement rencontré
- les contraintes qui ont fait changer le périmètre.</li>
- <li>le nombre d'aller-retours avec l'interlocuteur, et leur lenteur : quand nous
- avons pu mettre en place un appel vidéo journalier, beaucoup de choses se
- sont débloquées.</li>
- <li>dialogue avec le système distant très lent : nous aurions dû <a class="reference external" href="http://www.voidspace.org.uk/python/mock/">mock</a> beaucoup
- plus tôt le retour des requêtes Hive. Nous aurions ensuite dû récupérer un
- jeu de donnée complet (plusieurs Go) le plus tôt possible pour faire des
- tests sur le post-traitement dans un premier temps, puis ensuite seulement
- essayer d'améliorer les requêtes Hive. Faire les deux en même temps est une
- erreur qui nous a coûté de nombreux appels à Hive (et donc de nombreuses
- attentes et rétro-pédalages).</li>
- <li>peu de confiance dans les résultats : encore une fois vu la taille des
- données à traiter, il nous était très difficile de confronter nos données à
- celles attendues (uniquement disponibles en production). Nous avons fini par
- mettre en production un post-traitement parallèle à l'actuel, et stocker les
- données dans d'autres tables, en attendant d'avoir la version finale et
- raffinée de l'algorithme et des requêtes.</li>
- </ul>
- <p>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...</p>
- </div>
|