|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- <!doctype html><!-- This is a valid HTML5 document. -->
- <!-- Screen readers, SEO, extensions and so on. -->
- <html lang=fr>
- <!-- Has to be within the first 1024 bytes, hence before the <title>
- See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
- <meta charset=utf-8>
- <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
- <!-- The viewport meta is quite crowded and we are responsible for that.
- See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
- <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
- <!-- Required to make a valid HTML5 document. -->
- <title>Latence et boucle de rétroaction (archive) — David Larlet</title>
- <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
- <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
- <link rel="manifest" href="/manifest.json">
- <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
- <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
- <meta name="apple-mobile-web-app-title" content="David Larlet">
- <meta name="application-name" content="David Larlet">
- <meta name="msapplication-TileColor" content="#da532c">
- <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
- <meta name="theme-color" content="#f0f0ea">
- <!-- That good ol' feed, subscribe :p. -->
- <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
-
- <meta name="robots" content="noindex, nofollow">
- <meta content="origin-when-cross-origin" name="referrer">
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="http://mathieu.agopian.info/blog/latence-et-boucle-de-retroaction.html">
-
- <style>
- /* http://meyerweb.com/eric/tools/css/reset/ */
- html, body, div, span,
- h1, h2, h3, h4, h5, h6, p, blockquote, pre,
- a, abbr, address, big, cite, code,
- del, dfn, em, img, ins,
- small, strike, strong, tt, var,
- dl, dt, dd, ol, ul, li,
- fieldset, form, label, legend,
- table, caption, tbody, tfoot, thead, tr, th, td,
- article, aside, canvas, details, embed,
- figure, figcaption, footer, header, hgroup,
- menu, nav, output, ruby, section, summary,
- time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
- }
- /* HTML5 display-role reset for older browsers */
- article, aside, details, figcaption, figure,
- footer, header, hgroup, menu, nav, section { display: block; }
- body { line-height: 1; }
- blockquote, q { quotes: none; }
- blockquote:before, blockquote:after,
- q:before, q:after {
- content: '';
- content: none;
- }
- table {
- border-collapse: collapse;
- border-spacing: 0;
- }
-
- /* http://practicaltypography.com/equity.html */
- /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
- /* https://www.filamentgroup.com/lab/js-web-fonts.html */
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
- font-weight: 300;
- font-style: normal;
- font-display: swap;
- }
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
- font-weight: 300;
- font-style: italic;
- font-display: swap;
- }
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
- font-weight: 700;
- font-style: normal;
- font-display: swap;
- }
-
- @font-face {
- font-family: 'ConcourseT3';
- src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
- url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
- font-weight: 300;
- font-style: normal;
- font-display: swap;
- }
-
-
- /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
- body {
- /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
- font-family: "EquityTextB", Palatino, serif;
- background-color: #f0f0ea;
- color: #07486c;
- font-kerning: normal;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: subpixel-antialiased;
- text-rendering: optimizeLegibility;
- font-variant-ligatures: common-ligatures contextual;
- font-feature-settings: "kern", "liga", "clig", "calt";
- }
- pre, code, kbd, samp, var, tt {
- font-family: 'TriplicateT4c', monospace;
- }
- em {
- font-style: italic;
- color: #323a45;
- }
- strong {
- font-weight: bold;
- color: black;
- }
- nav {
- background-color: #323a45;
- color: #f0f0ea;
- display: flex;
- justify-content: space-around;
- padding: 1rem .5rem;
- }
- nav:last-child {
- border-bottom: 1vh solid #2d7474;
- }
- nav a {
- color: #f0f0ea;
- }
- nav abbr {
- border-bottom: 1px dotted white;
- }
-
- h1 {
- border-top: 1vh solid #2d7474;
- border-bottom: .2vh dotted #2d7474;
- background-color: #e3e1e1;
- color: #323a45;
- text-align: center;
- padding: 5rem 0 4rem 0;
- width: 100%;
- font-family: 'ConcourseT3';
- display: flex;
- flex-direction: column;
- }
- h1.single {
- padding-bottom: 10rem;
- }
- h1 span {
- position: absolute;
- top: 1vh;
- left: 20%;
- line-height: 0;
- }
- h1 span a {
- line-height: 1.7;
- padding: 1rem 1.2rem .6rem 1.2rem;
- border-radius: 0 0 6% 6%;
- background: #2d7474;
- font-size: 1.3rem;
- color: white;
- text-decoration: none;
- }
- h2 {
- margin: 4rem 0 1rem;
- border-top: .2vh solid #2d7474;
- padding-top: 1vh;
- }
- h3 {
- text-align: center;
- margin: 3rem 0 .75em;
- }
- hr {
- height: .4rem;
- width: .4rem;
- border-radius: .4rem;
- background: #07486c;
- margin: 2.5rem auto;
- }
- time {
- display: bloc;
- margin-left: 0 !important;
- }
- ul, ol {
- margin: 2rem;
- }
- ul {
- list-style-type: square;
- }
- a {
- text-decoration-skip-ink: auto;
- text-decoration-thickness: 0.05em;
- text-underline-offset: 0.09em;
- }
- article {
- max-width: 50rem;
- display: flex;
- flex-direction: column;
- margin: 2rem auto;
- }
- article.single {
- border-top: .2vh dotted #2d7474;
- margin: -6rem auto 1rem auto;
- background: #f0f0ea;
- padding: 2rem;
- }
- article p:last-child {
- margin-bottom: 1rem;
- }
- p {
- padding: 0 .5rem;
- margin-left: 3rem;
- }
- p + p,
- figure + p {
- margin-top: 2rem;
- }
-
- blockquote {
- background-color: #e3e1e1;
- border-left: .5vw solid #2d7474;
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 1rem;
- margin: 1.5rem;
- }
- blockquote cite {
- font-style: italic;
- }
- blockquote p {
- margin-left: 0;
- }
-
- figure {
- border-top: .2vh solid #2d7474;
- background-color: #e3e1e1;
- text-align: center;
- padding: 1.5rem 0;
- margin: 1rem 0 0;
- font-size: 1.5rem;
- width: 100%;
- }
- figure img {
- max-width: 250px;
- max-height: 250px;
- border: .5vw solid #323a45;
- padding: 1px;
- }
- figcaption {
- padding: 1rem;
- line-height: 1.4;
- }
- aside {
- display: flex;
- flex-direction: column;
- background-color: #e3e1e1;
- padding: 1rem 0;
- border-bottom: .2vh solid #07486c;
- }
- aside p {
- max-width: 50rem;
- margin: 0 auto;
- }
-
- /* https://fvsch.com/code/css-locks/ */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: 1rem;
- line-height: calc( 1.5em + 0.2 * 1rem );
- }
- h1 {
- font-size: 1.9rem;
- line-height: calc( 1.2em + 0.2 * 1rem );
- }
- h2 {
- font-size: 1.6rem;
- line-height: calc( 1.3em + 0.2 * 1rem );
- }
- h3 {
- font-size: 1.35rem;
- line-height: calc( 1.4em + 0.2 * 1rem );
- }
- @media (min-width: 20em) {
- /* The (100vw - 20rem) / (50 - 20) part
- resolves to 0-1rem, depending on the
- viewport width (between 20em and 50em). */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
- margin-left: 0;
- }
- h1 {
- font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- h2 {
- font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- h3 {
- font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- }
- @media (min-width: 50em) {
- /* The right part of the addition *must* be a
- rem value. In this example we *could* change
- the whole declaration to font-size:2.5rem,
- but if our baseline value was not expressed
- in rem we would have to use calc. */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: calc( 1rem + .6 * 1rem );
- line-height: 1.5em;
- }
- p, li, pre, details {
- margin-left: 3rem;
- }
- h1 {
- font-size: calc( 1.9rem + 1.5 * 1rem );
- line-height: 1.2em;
- }
- h2 {
- font-size: calc( 1.5rem + 1.5 * 1rem );
- line-height: 1.3em;
- }
- h3 {
- font-size: calc( 1.35rem + 1.5 * 1rem );
- line-height: 1.4em;
- }
- figure img {
- max-width: 500px;
- max-height: 500px;
- }
- }
-
- figure.unsquared {
- margin-bottom: 1.5rem;
- }
- figure.unsquared img {
- height: inherit;
- }
-
-
-
- @media print {
- body { font-size: 100%; }
- a:after { content: " (" attr(href) ")"; }
- a, a:link, a:visited, a:after {
- text-decoration: underline;
- text-shadow: none !important;
- background-image: none !important;
- background: white;
- color: black;
- }
- abbr[title] { border-bottom: 0; }
- abbr[title]:after { content: " (" attr(title) ")"; }
- img { page-break-inside: avoid; }
- @page { margin: 2cm .5cm; }
- h1, h2, h3 { page-break-after: avoid; }
- p3 { orphans: 3; widows: 3; }
- img {
- max-width: 250px !important;
- max-height: 250px !important;
- }
- nav, aside { display: none; }
- }
-
- ul.with_columns {
- column-count: 1;
- }
- @media (min-width: 20em) {
- ul.with_columns {
- column-count: 2;
- }
- }
- @media (min-width: 50em) {
- ul.with_columns {
- column-count: 3;
- }
- }
- ul.with_two_columns {
- column-count: 1;
- }
- @media (min-width: 20em) {
- ul.with_two_columns {
- column-count: 1;
- }
- }
- @media (min-width: 50em) {
- ul.with_two_columns {
- column-count: 2;
- }
- }
-
- .gallery {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-around;
- }
- .gallery figure img {
- margin-left: 1rem;
- margin-right: 1rem;
- }
- .gallery figure figcaption {
- font-family: 'ConcourseT3'
- }
-
- footer {
- font-family: 'ConcourseT3';
- display: flex;
- flex-direction: column;
- border-top: 3px solid white;
- padding: 4rem 0;
- background-color: #07486c;
- color: white;
- }
- footer > * {
- max-width: 50rem;
- margin: 0 auto;
- }
- footer a {
- color: #f1c40f;
- }
- footer .avatar {
- width: 200px;
- height: 200px;
- border-radius: 50%;
- float: left;
- -webkit-shape-outside: circle();
- shape-outside: circle();
- margin-right: 2rem;
- padding: 2px 5px 5px 2px;
- background: white;
- border-left: 1px solid #f1c40f;
- border-top: 1px solid #f1c40f;
- border-right: 5px solid #f1c40f;
- border-bottom: 5px solid #f1c40f;
- }
- </style>
-
- <h1>
- <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
- Latence et boucle de rétroaction (archive)
- <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
- </h1>
- <section>
- <article>
- <h3><a href="http://mathieu.agopian.info/blog/latence-et-boucle-de-retroaction.html">Source originale du contenu</a></h3>
- <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>
-
- <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></p>
- </article>
- </section>
-
-
- <nav id="jumpto">
- <p>
- <a href="/david/blog/">Accueil du blog</a> |
- <a href="http://mathieu.agopian.info/blog/latence-et-boucle-de-retroaction.html">Source originale</a> |
- <a href="/david/stream/2019/">Accueil du flux</a>
- </p>
- </nav>
-
- <footer>
- <div>
- <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
- <p>
- Bonjour/Hi!
- Je suis <a href="/david/" title="Profil public">David Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
- Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
- </p>
- <p>
- Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
- </p>
-
- <p>
- Voici quelques articles choisis :
- <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
- <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
- <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
- <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
- <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
- <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
- <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
- <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
- <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
- <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
- <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
- <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
- <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
- <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
- <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
- et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
- </p>
- <p>
- On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
- </p>
- <p>
- Je ne traque pas ta navigation mais mon
- <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
- conserve des logs d’accès.
- </p>
- </div>
- </footer>
- <script type="text/javascript">
- ;(_ => {
- const jumper = document.getElementById('jumper')
- jumper.addEventListener('click', e => {
- e.preventDefault()
- const anchor = e.target.getAttribute('href')
- const targetEl = document.getElementById(anchor.substring(1))
- targetEl.scrollIntoView({behavior: 'smooth'})
- })
- })()
- </script>
|