Aller au contenu

Blog ·

Une barre de progression qui refuse de deviner

La plupart des estimations de durée sont inventées. Voici la règle qui décide quand notre panneau a le droit d’en afficher une, et ce qu’il dit sinon.

Par Provibr

Quelqu’un clique sur installer. Une machine doit être clonée, démarrée, configurée et vérifiée, et quelque part au milieu de tout cela le client veut savoir une seule chose : combien de temps cela va prendre.

La réponse facile, c’est un compte à rebours. Choisir un nombre plausible, retrancher une seconde chaque seconde, et l’écran a l’air de savoir quelque chose. Il ne sait rien. Un compte à rebours est une promesse portant sur un instant, et personne dans la maison ne connaît cet instant.

Nous avons donc écrit la règle, nous lui avons donné un numéro de version, et nous avons fait dire au panneau, à voix haute, quand il n’y a pas droit.

La règle, en bref

Une estimation de durée n’apparaît que si deux conditions sont vraies en même temps. Il faut au moins vingt exécutions réussies du même type de travail au cours des trente derniers jours, et la dispersion doit être serrée : le quatre-vingt-dixième centile ne peut pas dépasser deux fois et demie la médiane. Si l’une des deux échoue, l’écran affiche l’étape, le temps écoulé et une phrase qui dit qu’il n’y a pas d’estimation.

Ces trois nombres vivent dans une seule constante, avec un champ de version à côté d’eux, et rien d’autre dans le code n’a le droit d’avoir un avis dessus.

SituationCe que l’écran affiche
Moins de vingt exécutions comparables en trente jours« No reliable time estimate yet » (pas encore d’estimation de durée fiable), avec le nombre d’exécutions enregistrées et le nombre nécessaire
Vingt ou plus en trente jours, mais la dispersion est trop large« No reliable time estimate », et que les exécutions étaient trop éloignées les unes des autres
Les deux conditions remplies« Comparable tasks took X to Y minutes, based on N runs in the last 30 days »

Lisez la troisième ligne attentivement. C’est une fourchette, et elle nomme ses propres preuves. Ce n’est pas une barre qui rampe vers une ligne d’arrivée, et elle ne se transforme jamais en « il reste 3 minutes ».

Pourquoi une fourchette et pas un compte à rebours

Un compte à rebours cumule deux erreurs. Il masque l’incertitude, et il se réaffirme chaque seconde, si bien que la fausseté prend un rythme. Tout le monde a déjà vu une boîte de dialogue de copie promettre quatre minutes, puis quatorze, puis deux, et a appris en une trentaine de secondes que le nombre ne veut rien dire. Une fois que le lecteur a appris cela, tous les autres nombres de l’écran valent un peu moins. Une fourchette, énoncée une seule fois avec son nombre d’échantillons attaché, ne peut pas faire cela.

C’est la condition sur la dispersion qui fait le vrai travail. Vingt échantillons avec une médiane de quatre minutes et un quatre-vingt-dixième centile de quarante minutes ne forment pas une cohorte contenant une prédiction ; ce sont deux populations différentes portant une seule étiquette, et en faire la moyenne produit un chiffre avec une virgule et sans signification. Deux et demi est un nombre choisi, pas un nombre dérivé, et le champ de version existe pour que le modifier plus tard soit une décision visible.

La cohorte, c’est votre propre compte, et c’est délibéré

La façon évidente d’atteindre vingt échantillons rapidement serait de mesurer sur l’ensemble de la plateforme. Nous ne le faisons pas. La cohorte, c’est le type de travail au sein d’une seule organisation.

Il y a deux raisons, et c’est la seconde qui a tranché.

La première est la comparabilité. Votre propre historique est la population la plus semblable qui existe : le même hyperviseur, le même réseau, les mêmes images, le même stockage.

La seconde est que le nombre d’échantillons est affiché à l’écran. Une phrase qui indique combien d’exécutions comparables la plateforme a vues en trente jours est une affirmation sur notre propre volume, imprimée dans le panneau d’un client, et elle serait distribuée en échange d’une estimation légèrement meilleure. Limiter la requête à une seule organisation fait que le nombre affiché sur votre écran est un fait qui vous concerne, vous.

La conséquence pratique, c’est qu’un compte récent ne voit aucune estimation pendant un certain temps, et c’est le comportement correct plutôt qu’un vide à combler. Ne rien afficher vaut mieux qu’afficher un nombre qui ne veut rien dire.

Il n’existe pas de table d’échantillons

La durée d’une tâche réussie est la différence entre deux horodatages déjà stockés sur la tâche elle-même. Il n’existe pas de table de mesures séparée.

Cela ressemble à une économie évidente, et il vaut la peine de dire pourquoi c’était une décision. Une seconde table contiendrait deux fois la même vérité, et les deux divergeraient dès la première passe de rétention qui toucherait l’une et pas l’autre. La seule chose qu’elle apporterait vraiment, ce sont des échantillons qui survivent aux tâches dont ils proviennent, et cela ne compte qu’à partir du moment où la durée de rétention est plus courte que la fenêtre de mesure. Aujourd’hui la rétention est de quatre-vingt-dix jours et la fenêtre de trente : la question ne se pose pas.

Une note de bas de page qui a déjà mordu ce code : la requête de centile renvoie un double et le décompte renvoie un bigint, que le pilote restitue sous forme de chaîne. Les deux ont besoin d’une conversion, et en oublier exactement un des deux échoue en silence plutôt que bruyamment.

Des étapes, parce qu’un pourcentage doit bien venir de quelque part

Chaque type de tâche porte une liste d’étapes dans l’ordre. Une installation passe par : en file d’attente, préparation, démarrage, installation, finalisation. Un téléchargement depuis une URL passe par : en file d’attente, envoyé à l’agent, téléchargement, vérification, application. Le pourcentage est dérivé de la position dans cette liste, sauf si le travail sous-jacent rapporte lui-même un pourcentage réel, auquel cas c’est celui-là qui gagne.

Cette priorité compte plus qu’il n’y paraît. Une installation rapporte son propre chiffre de progression et il est affiché sur la page propre à ce serveur ; si le tiroir calculait un second nombre à partir des positions d’étapes, un même écran porterait deux pourcentages différents sur le même travail. C’est une seconde copie de la vérité, un étage plus haut.

La traduction des phases d’installation vers les étapes tient à un seul endroit, écrite comme un enregistrement exhaustif plutôt que comme un branchement. Quatorze phases réparties sur deux échelles d’installation différentes se ramènent à cinq étapes qu’un client reconnaîtrait. Une nouvelle phase est une erreur de compilation, pas une étape qui retombe discrètement sur la première.

Périmé n’est pas en échec

Il y a deux seuils sur la fraîcheur du dernier rapport de progression : deux minutes et dix minutes. Passé le premier, l’écran dit qu’il n’y a pas eu de mise à jour depuis une heure donnée. Passé le second, il dit que plus rien n’a été rapporté depuis ce moment.

Aucun des deux ne change le statut. Le travail peut se dérouler parfaitement. Ce qui s’est arrêté, c’est le rapport, et un lecteur mérite qu’on le lui dise plutôt que de regarder une barre immobile et d’en tirer ses propres conclusions. Confondre le silence avec l’échec est la même erreur que fermer un incident parce que les mesures ont cessé d’arriver, et il vaut la peine de garder les deux mots séparés partout où ils apparaissent.

Le tiroir ne possède rien

Le tiroir des tâches d’arrière-plan, dans l’en-tête, se pose au-dessus de tout cela, et sa règle de conception est courte : il ne détient aucun état propre au sujet du travail. Le seul état local de ce composant est de savoir si le panneau est ouvert. Il n’y a pas de boucle de récupération, pas d’intervalle, pas de second socket. L’état initial arrive de la même requête que celle qu’utilise la page de détail, et les mises à jour en direct arrivent par le magasin temps réel partagé.

Un test lit l’arbre syntaxique du composant et échoue si un état local vient à contenir un statut, une étape ou un pourcentage. C’est une garantie plus forte qu’une relecture de code, pour la même raison qu’un commentaire n’est pas un test.

Un détail là-dedans se prend facilement à l’envers : les groupes du tiroir sont calculés après application du correctif en direct, pas avant. Calculez-les d’abord et une tâche qui vient d’échouer reste assise dans le groupe des tâches en cours jusqu’au prochain chargement complet de la page, affichant discrètement un indicateur d’activité à côté de quelque chose qui est déjà rouge.

Trois défauts que seule la vérification a trouvés

Tous les trois compilaient, passaient le contrôle de types et passaient les tests unitaires.

Le reçu n’était écrit nulle part. Le code faisait référence à une fonction qui n’existait pas, si bien qu’une installation réussie produisait une tâche dont la section de résultat restait vide pour toujours.

Une phase d’installation non reconnue effaçait l’étape enregistrée. La correspondance ne renvoie correctement rien pour une phase qu’elle ne connaît pas, mais l’appelant écrivait ce rien dans la ligne : un agent plus ancien rapportant une phase renommée aurait donc effacé l’étape d’une tâche qui tournait très bien. Le correctif tient en un repli sur l’étape déjà présente, et le garde-fou a été prouvé rouge avant qu’on lui fasse confiance.

Une tâche terminée continuait de tourner. L’étape d’une tâche achevée reste la dernière étape qu’elle a atteinte, ce qui est correct, car sinon on ne pourrait pas voir où elle s’est arrêtée. Le bogue consistait à demander « cette étape est-elle l’étape courante » en comparant des noms, alors que la vraie question est de savoir si la tâche est encore active. Une tâche en échec ne reçoit pas non plus de coche verte sur l’étape où elle est morte : cette étape a été abandonnée plutôt qu’achevée, elle a donc un état à elle au lieu d’être classée sous terminée ou non commencée, deux classements qui affirmeraient quelque chose de faux.

Ce que nous retiendrions

  1. Mettez la règle d’estimation dans une seule constante versionnée. La question « l’estimation que vous avez affichée en mars était-elle défendable » n’a de réponse que si l’on sait quelle règle était en vigueur.
  2. Faites de l’absence d’estimation une phrase, pas un espace vide. Un blanc là où devrait se trouver un nombre se lit comme un bogue ; « No reliable time estimate yet. 6 of 20 comparable runs recorded. » se lit comme un système qui sait ce qu’il ignore.
  3. Limitez la cohorte au client, et acceptez que les nouveaux comptes ne voient rien pendant un temps. L’autre solution imprime votre propre volume sur leur écran.
  4. Ne laissez jamais un tiroir, une pastille ou un widget détenir sa propre copie d’un statut. Deux nombres sur un même travail sur un même écran, c’est pire qu’aucun nombre.
  5. Séparez le silence de l’échec dans le vocabulaire, dans le modèle de données et à l’écran, et gardez-les séparés partout.

Les limites honnêtes : cette couche fonctionne aujourd’hui pour quatre types de travail, et la liste est volontairement courte parce qu’un type que personne ne peut lancer est une catégorie qui s’affiche vide. Le flux d’annulation peut enregistrer une demande mais aucune couche d’exécution n’en confirme encore une, et le tiroir n’a pas de point d’entrée en dessous de 768 pixels de largeur d’écran.

Le même raisonnement, appliqué à la chose à laquelle une barre de progression est habituellement attachée, se trouve dans pourquoi un 200 de Proxmox n’est pas un résultat, et la raison pour laquelle nous avons cessé de faire confiance à nos propres délais est dans un délai n’est pas un bouton d’arrêt.

Issu du travail de plateforme sur Provibr.

Commencez avec un hôte et un agent

Créez un compte, installez l’agent avec une seule commande et connectez votre premier hôte Proxmox. La période d’essai dure 14 jours et ne demande aucune coordonnée de paiement.