3 points par GN⁺ 2023-09-01 | 2 commentaires | Partager sur WhatsApp
  • Marginalia Search a récemment réduit de moitié ses besoins en RAM grâce à des changements, et a fortement diminué la charge opérationnelle qui l’obligeait à arrêter le moteur de recherche pendant les mises à niveau
  • La panne est apparue lors du basculement d’index après la dernière version, et l’architecture qui supprimait la base de données d’URL lors des mises à niveau entraînait de longues périodes hors ligne
  • Le stockage des URL est passé d’une énorme table MariaDB centrée sur ses index à une unique base de données SQLite et à une structure d’ID d’URL 64 bits générés par le processus
  • La construction de l’index inversé abandonne le lexicon pour des term ID denses et les grandes écritures aléatoires, au profit de petits preindex ensuite fusionnés
  • La nouvelle architecture permet, même en cas de mauvais déploiement, de restaurer en quelques heures à partir de sauvegardes de fichiers, et facilite la réutilisation des résultats de traitement de grands jeux de données qui changent peu, comme Wikipedia

Des conditions d’exploitation du moteur de recherche transformées en une semaine

  • Marginalia Search a réduit simultanément plusieurs problèmes de long terme en une semaine de codage
    • Les besoins en RAM du moteur de recherche ont été divisés par deux
    • Il n’est plus nécessaire de mettre le système hors ligne pendant les mises à niveau
    • La limite stricte du nombre de documents indexables a été supprimée
    • La limite souple du nombre de mots-clés pouvant être inclus dans le corpus a été multipliée par 4
  • L’objectif de long terme était de permettre au système de continuer à fonctionner même sur du matériel peu performant, et ce changement représente une amélioration plus importante encore que les précédentes optimisations qui rendaient confortable l’usage d’une machine de développement avec 32 Go de RAM

L’ancienne architecture de mise à niveau qui a aggravé la panne

  • Marginalia Search est resté hors ligne pendant près d’une semaine à cause d’un problème lié à la dernière version
  • La cause directe était une chaîne de problèmes de scalabilité relativement mineurs, mais il a fallu redémarrer plusieurs fois un processus qui prend normalement 1 jour, ou 2 à 3 jours en cas de problème
    • La plupart des redémarrages étaient dus à un manque de RAM
  • La panne a été très visible pour les utilisateurs parce que le système devait être mis hors ligne pendant le basculement d’index
  • Dans l’ancienne architecture, la base de données d’URL était supprimée pendant les mises à niveau, et l’insertion et la mise à jour rapides de lignes dans une table approchant le milliard d’entrées devenaient un goulet d’étranglement
    • Le processus de chargement des nouvelles données utilisait beaucoup de RAM
    • Il était difficile de l’exécuter en même temps que le service d’indexation, qui consommait la RAM de la même façon
    • La clé primaire étant un entier 32 bits, il existait une limite qui rendait difficile le dépassement des 2 milliards

Refonte de la base de données d’URL

  • La base de données d’URL était un composant ancien du moteur de recherche, et ses décisions de conception initiales ne correspondaient plus à l’architecture actuelle du système
  • Au cœur du système se trouvaient deux tables utilisées uniquement lors du chargement d’un nouvel index, et lues uniquement par recherche sur clé primaire
    • La table URL attribue un identifiant numérique unique à chaque URL
    • La table PAGE_DATA contient des informations comme le titre et la description des liens indexés
    • Il existait un index supplémentaire pour maintenir l’unicité des chemins au sein d’un domaine, mais il était très volumineux au regard de son rôle
  • La nouvelle architecture fusionne les deux tables dans une base de données SQLite à table unique, confie au processus de chargement la génération des ID uniques, et gère dans une table séparée la liste des URL à ne pas indexer
  • L’usage conjoint de MariaDB et SQLite n’est pas un choix conventionnel, mais les deux stockages répondent à des besoins différents
    • Le système a besoin d’une vision persistante du monde relativement petite
    • En même temps, il doit pouvoir remplacer des états de l’ordre du téraoctet en mode plug-and-play
  • Les tables DOCUMENT et DOMAIN sont faiblement liées entre bases de données, mais aucune jointure réelle n’est nécessaire
    • En situation de désastre, les parties importantes de la table DOMAIN peuvent être reconstruites à partir de la table DOCUMENT

Créer des ID d’URL 64 bits sans index

  • L’ancienne table URL utilisait des ID 32 bits, et le fait d’être proche d’un dépassement d’entier était un problème de scalabilité connu
  • L’une des raisons pour lesquelles la base de données d’URL était supprimée était aussi d’éviter que la colonne d’ID ne déborde
  • Un simple compteur ne suffit pas à gérer les URL répétées, et il fallait aussi éviter de conserver en mémoire la collection de toutes les URL déjà vues
  • La nouvelle méthode ne laisse pas la base de données attribuer les ID : elle construit directement des ID 64 bits
    • Les 26 bits de poids faible sont utilisés comme numéro de séquence
    • Les bits 26 à 56 sont utilisés comme ID de document
    • Les bits de poids fort sont réservés à des astuces de tri de l’index
  • Cette répartition autorise environ 67 millions de documents par domaine
    • C’est environ 10 fois la taille de Wikipedia en anglais
    • Jusqu’à 2 milliards de domaines sont possibles
    • C’est près de 100 fois le nombre de domaines pour lesquels Marginalia a vu une référence quelque part sur le Web
  • La responsabilité de l’intégrité des données passe de la base de données au processus de génération des données, mais le coût pour l’imposer y est beaucoup plus faible

La refonte des URL réduit la pression mémoire

  • En supprimant les énormes index et la grande table qui mélangeait données d’URL chaudes et froides, le serveur MariaDB n’a plus besoin de 36 Go de RAM
  • Les données chaudes restantes dans MariaDB représentent au plus quelques centaines de Mo, et il est probable qu’il ne soit plus nécessaire d’allouer plus de 2 Go de RAM au serveur
  • Les données SQLite ont encore besoin d’un index pour la clé primaire, mais la partie réellement chaude de l’index devrait rester sous 1 Go
    • Le volume de données indexées diminue d’un ordre de grandeur
    • La cible de l’index est un unique long 64 bits
    • Il n’y a pas de contrainte d’unicité supplémentaire
  • Le fait que la sortie du loader devienne un ensemble de fichiers facilite la création de sauvegardes automatiques
  • Même en cas de mauvais déploiement, la restauration peut se faire en quelques heures, et non plus en près d’une semaine comme auparavant

Le goulet d’étranglement de la construction de l’index inversé

  • Le loader produit la base de données d’URL et un journal centré sur les documents, de la forme (document, words[]), tandis que la recherche a besoin d’un index transposé sous la forme (word, documents[])
  • L’ancienne méthode utilisait un lexicon qui associait les chaînes de mots-clés à des term ID denses
    • Le premier mot recevait l’ID 0, le mot suivant l’ID 1, et ainsi de suite
    • Les chaînes étaient associées à des long via un hachage 64 bits
    • La structure était en pratique une table de hachage ouverte long-to-int
  • Cette structure se remplit facilement à grande échelle
    • Java n’autorise pas les tableaux de plus de 2 milliards d’éléments
    • L’implémentation utilisée bloque déjà autour du milliard d’éléments
    • À 1 milliard d’entrées, elle utilise 12 Go de RAM
  • L’index service en production utilise 60 Go de RAM, en grande partie hors tas
  • Le fait que la taille on-heap dépasse 32 Go, ce qui rend difficile l’usage de CompressedOOPs, posait également problème

L’amplification d’écriture de l’ancien algorithme d’index inversé

  • L’ancien algorithme trouvait le plus grand word ID, créait un tableau counts de cette taille, puis calculait la position des documents pour chaque mot afin d’écrire les données de documents dans un fichier mappé en mémoire
  • Cette méthode avait besoin du lexicon parce qu’elle supposait que le domaine des word ID était densément rempli
  • Le plus grand goulet d’étranglement était l’écriture d’environ 1 To de données dans un fichier mappé en mémoire, presque entièrement dans un ordre aléatoire
  • Les SSD gèrent bien les accès aléatoires en lecture, mais les petites écritures provoquent un problème d’amplification d’écriture (write amplification)
    • Même pour modifier un seul octet sur le disque, un SSD doit effacer puis réécrire une page entière
    • Il existe des caches qui regroupent les écritures adjacentes, mais ils ne sont pas efficaces face à des écritures aléatoires à l’échelle du téraoctet
    • Pendant l’écriture de 1 To, le disque finit par écrire environ 0,5 Po
  • Une mesure d’atténuation temporaire, RandomWriteFunnel, existait
    • Les écritures étaient d’abord réparties dans de petits fichiers bucket
    • Un grand fichier était ensuite écrit séquentiellement
    • C’était mieux que la méthode d’origine, mais restait très lent

Créer de petits preindex puis les fusionner

  • La nouvelle construction de l’index inversé consiste à créer plusieurs petits index dont toutes les données tiennent en mémoire, puis à les fusionner
  • La fusion de listes triées est rapide et convient même aux disques durs mécaniques
  • Avec cette méthode, le lexicon n’est plus nécessaire
    • Un hachage de chaîne 64 bits peut être utilisé directement comme term ID
  • Les problèmes apparus au départ tenaient au fait que l’entrée était compressée et à la manière de fusionner les index
    • Au lieu de lire rapidement une partie de l’entrée compressée, on crée plusieurs petits fichiers et on les lit un par un
    • Au lieu de fusionner les index après leur création, on fusionne les données avant de créer les index
  • La nouvelle abstraction, preindex, se compose d’un tableau d’ID de mots, d’un tableau de comptes et d’un tableau de données de documents
  • Comme l’entrée est petite, la plupart des preindex peuvent être créés en RAM, validés sur disque au fil de la génération, puis servir à produire le preindex final lors d’une étape de fusion ultérieure
  • Le preindex final est transformé en index inversé comme auparavant, en ajoutant un index btree statique à la table des mots et à chaque document block ; ce processus est relativement rapide

Changements pour l’exploitation et la réutilisation des données

  • La suppression du lexicon a réduit les besoins en RAM, et la nouvelle construction de l’index inversé est plus rapide que l’ancien algorithme
  • L’ancien lexicon créait un dialecte distinct pour chaque lot de données traité
    • Un même mot pouvait recevoir un certain ID lors d’une exécution, puis un autre ID lors d’une autre exécution
    • Cela obligeait à traiter toutes les données en même temps
  • En abandonnant le lexicon, il devient possible de fusionner différents lots de données
  • Les résultats de traitement de grands jeux de données qui changent rarement, comme Wikipedia, peuvent être réutilisés et combinés avec des données d’index qui évoluent plus fréquemment
  • Ce changement réduit presque tous les problèmes de scalabilité connus et les frictions opérationnelles, et met le système en position d’examiner davantage d’effets secondaires

2 commentaires

 
GN⁺ 2023-09-01
Avis sur Hacker News
  • Voir ce genre de réussite dans un projet qui va à l’exact opposé du reste du monde, ça fait vraiment plaisir
    J’aimerais appeler ça Engildification, et il devrait y en avoir davantage comme ça
    J’ai aussi aimé l’article Sleeping At Night, et avec le récent article « Lie Still in Bed », ça ressemble à une option très simple pour corriger les problèmes d’entraînement au sommeil

    • Ça ressemble à une fonction de la taille. Plus l’équipe ou l’entreprise derrière le produit est grande, plus le coefficient et la probabilité d’enshittification augmentent
      Le moteur de recherche Marginalia est ce qu’il y a de plus éloigné du risque d’enshittification : son auteur est récemment passé à plein temps dessus et, à ma connaissance, l’équipe compte une seule personne. C’est justement à cette échelle que naissent les pépites, et que la créativité, l’originalité et la vision peuvent briller
      Ce commentaire vous est offert par le collectif « quittons nos jobs de bureau pour travailler en indépendant »
    • Les 3 derniers articles sont vraiment rafraîchissants
      Il a réduit de moitié la consommation de ressources, il est devenu plus productif qu’avant sur un écran plus petit, et la nuit il dort comme une souche
    • Comme je galère avec des problèmes de sommeil cette année, savoir ce qui a marché pour quelqu’un d’autre est assez utile
      Lien pour les personnes intéressées : https://www.marginalia.nu/log/86-sleep/
    • J’aime bien l’expression engildification
    • Ce genre de cas existe bel et bien. C’est juste qu’on ne les trouvera jamais avec Google
  • À noter que le moteur de recherche payant Kagi, que vous avez peut-être déjà vu sur Hacker News, utilise Marginalia comme l’une de ses sources de données
    https://help.kagi.com/kagi/search-details/search-sources.htm...
    Avec la lentille « non-commercial », ce type de résultats est mis en avant aux côtés des résultats de l’index propre à Kagi et de quelques sources indépendantes

  • En lisant cet article, je me demande si les humains ne seraient pas des êtres qui ont du mal à créer quelque chose d’excellent sans contraintes artificielles.
    Si Marginalia est aussi absurdement efficace, c’est parce que Victor limite intentionnellement le matériel d’exécution et la capacité mémoire.
    Ajouter simplement 32 Gio de plus permettrait probablement de tenir quelque temps, mais la conception inefficace resterait, et le même problème pourrait réapparaître plus tard dans un système devenu plus complexe, donc plus difficile à corriger.
    Si cette hypothèse est juste, elle explique aussi pourquoi les logiciels actuels sont gonflés, lents et pleins de bugs. Chaque logiciel, pris isolément, n’atteint presque jamais ses limites ; chaque morceau peut donc être inefficace, tandis que les M2 Pro récents et les connexions en Gio continuent de dépasser le point où le problème se manifesterait.
    La conclusion pourrait être qu’à long terme, se limiter soi-même est meilleur pour soi comme pour tout le monde.

    • C’est surtout une question de priorités.
      Dans beaucoup d’applications, passer autant de temps sur de petites optimisations n’a pas vraiment de sens. Quand on peut ajouter 32 Gio de RAM à un serveur pour moins de 50 dollars, comparé au choix de mobiliser un développeur plus de 40 heures à au moins 20 dollars de l’heure, la réponse est évidente du point de vue business. En plus, le site web est resté hors ligne pendant toute une semaine, ce qui, à lui seul, pourrait tuer la plupart des entreprises.
      Les techniciens aiment ce genre d’exploration en profondeur, au point de vouloir micro-optimiser pendant des années même du code trivial, mais on ne gagne pas d’argent avec une tonte de yak sans fin. Si le code ne tourne que sur une toute petite poignée de machines, cela n’en vaut généralement pas la peine. Ce genre d’optimisation finit aussi souvent par produire du code plus difficile à maintenir.
      Je pense que la bloatwareisation des applis qui tournent aujourd’hui sur les appareils des utilisateurs vient en grande partie du décalage entre les machines des développeurs et celles des utilisateurs. Les développeurs ont besoin de stations de travail performantes pour faire leur travail et les utilisent aussi pour les tests de base, alors que les utilisateurs exécutent l’appli sur des appareils qui étaient déjà milieu de gamme ou moins il y a cinq ans.
      Il est difficile de vendre à un manager « on peut économiser 150 Mo de mémoire », mais on peut lui vendre « économiser 150 Mo de mémoire fera passer les performances de l’appli, pour 10 % des utilisateurs, de catastrophiques à tout juste utilisables ».
    • Je suis d’accord avec ce point de vue. La contrainte engendre l’ingéniosité, et cela ne vaut pas seulement pour les productions de la demoscene. Les problèmes de scalabilité finissent toujours par arriver, et il est beaucoup plus simple de les traiter tôt que tard. Si un logiciel tourne bien sur un Raspberry Pi, il sera absurdement rapide sur un vrai serveur.
      Autrefois, on concevait vraiment les logiciels comme ça. C’est pour cela qu’un système d’exploitation offrant la plupart de ce que l’on attend aujourd’hui pouvait très bien tourner sur des machines comme un Pentium 1. À l’inverse, aujourd’hui, même sur des smartphones qui disposent littéralement d’environ mille fois plus de ressources sur tous les axes, le défilement d’une page web saccade. L’équipe de Word 95 se heurtait constamment aux limites et aux compromis de performance, et le résultat marchait clairement, ou ne marchait pas.
      S’ils avaient simplement ajouté plus de RAM, ils seraient restés enfermés dans une conception inférieure, et auraient bientôt dû racheter encore plus de RAM. Ce qui est remarquable dans ce changement, ce n’est pas seulement la baisse de l’utilisation des ressources : c’est aussi que la RAM libérée augmente le cache disque, rendant le système plus capable et plus rapide.
      [1] Par exemple, ceci tourne sur un seul Pi et, comme les mises à jour ne sont pas autorisées, c’est beaucoup plus rapide que Wikipedia en production : https://encyclopedia.marginalia.nu/article/Hacker_News
    • C’est aussi une hypothèse que j’aime bien.
      C’est peut-être pour cela que les vieux ordinateurs semblaient agréables, et que les vieux jeux pouvaient être aussi excellents.
      Cela a peut-être à voir avec la complexité des systèmes que nous manipulons. Quand les ressources — RAM, espace physique, nourriture, matériaux, temps, argent — sont limitées, il faut planifier leur utilisation, et l’on est forcé de devenir malin.
      Avec des ressources pratiquement infinies, on peut construire comme on veut, mais on a moins besoin de se soucier de l’état final. On commence, puis on verra bien quand ça tournera.
      Je ne suis pas vraiment un gamer, mais je suis toujours étonné par la capacité humaine à faire tenir autant d’émotions, d’aventure et d’heures de plaisir dans des cartouches ROM de quelques Ko/Mo. La ROM d’Ocarina Of Time ne fait qu’environ la taille de 8 photos récentes prises avec mon iPhone.
    • Au milieu des années 1970, American Airlines faisait tourner SABRE, son système de billetterie et de réservation aérienne, sur deux mainframes System/360, avec un débit de seulement quelques dizaines de millions d’instructions par seconde.
      Un Raspberry Pi 2 peut exécuter plus de 4 milliards d’instructions Dhrystone par seconde, et un Pi 4 plus de 10 milliards.
      Bien sûr, selon les standards modernes, le SABRE du milieu des années 1970 était assez basique pour un système cœur de métier d’une compagnie aérienne, mais en théorie, il serait possible de faire tourner simultanément, sur un seul Pi 2, les systèmes simplifiés de plus de 100 compagnies aériennes.
      Les programmes modernes sont très loin d’être optimisés. Sauf dans les cas très chargés en calcul mathématique, des améliorations de 1000x ou 10000x sont possibles.
    • Le point sur le fait que chaque élément, pris séparément, n’atteint pas ses limites est très bon.
      Je pense que Microsoft souffre fortement de ce problème. Même un ordinateur portable à 3000 dollars d’il y a cinq ans devient d’une lenteur difficilement acceptable quand on lance en même temps un appel Teams, quelques applications Office et un navigateur avec 30 onglets.
      Testés séparément, chacun va bien quand il est seul, mais les vrais gens n’utilisent pas leur machine comme ça.
      Une solution pourrait être d’imposer des limites artificielles au temps d’exécution sur un matériel clairement défini, et de ne relever ces limites qu’après une décision explicite.
      Cela dit, je n’écris que des logiciels métier où l’aspect performance se résume à « ne faites pas n’importe quoi avec la base de données, et pour le reste, ne vous en préoccupez pas puisque les clients ne paient pas pour ça », donc je suis peut-être complètement à côté de la plaque.
  • Je suis toujours content quand une mise à jour de marginalia.nu arrive. C’est un utilisateur précieux sur ce site, et j’espère qu’il continuera à publier.

  • Merci. Je travaille sur un moteur de recherche comme projet perso, et pour une raison quelconque je continuais à chercher uniquement des variantes de « Magnolia ». Le nom Marginalia ne me reste pas bien en tête. En ce moment, j’essaie de comprendre Searx.
    Je me demande si Marginalia prend en charge des recherches avec des filtres temporels, comme la veille ou la semaine précédente. À regarder les mots-clés spéciaux, les paramètres de recherche semblent ne prendre que des critères basés sur l’année.
    year>2005 (beta) le document semble avoir été publié après 2005
    year=2005 (beta) le document semble avoir été publié en 2005
    year<2005 (beta) le document semble avoir été publié avant 2005

    • L’index de recherche n’est pas mis à jour plus d’une fois par mois, donc il n’y a pas ce genre de filtre.
      Même les filtres par année sont assez approximatifs, et il est très difficile de déterminer précisément la date de la plupart des pages web.
    • C’est un moteur de recherche pour les contenus de niche. Autrement dit, pour les contenus en marge ; le nom Marginalia se comprend donc.
  • Je me demande si l’affirmation selon laquelle « chaque fois qu’un SSD met à jour un seul octet quelque part sur le disque, il doit effacer puis réécrire toute une page » est réellement vraie pour les SSD
    Ce n’est pas le cas avec la flash brute. C’est possible si l’on écrase une valeur « vide » composée uniquement de 1, ou si l’on ne fait que transformer des 1 en 0. Les écritures sont plusieurs ordres de grandeur plus lentes que les lectures, mais aussi plusieurs ordres de grandeur plus rapides que les effacements, et seul l’effacement compte dans le budget d’usure
    Si le contrôleur du SSD n’exploite pas cela, ça ressemble à un but contre son camp. Cela dit, si l’intérieur est réellement structuré en journal, il se peut qu’il ne puisse pas le faire

    • Ça peut dépendre des cas
      Il y a quelque temps, j’ai écrit des pilotes pour plusieurs puces flash populaires, et toutes celles que j’ai utilisées à l’époque ne prenaient en charge, en lecture comme en écriture, que des entrées/sorties par pages de taille fixe
      Un SSD étant un ensemble de puces, je m’attendrais à ce que chaque puce à l’intérieur du SSD ne prenne elle aussi en charge que des E/S par pages de taille fixe
    • Dans ce cas, on était en réalité en train de réécrire l’intégralité du disque dur dans un ordre complètement aléatoire, ce qui est le pire des cas pour un SSD
      En général, les contrôleurs utilisent diverses techniques — surprovisionnement, buffering, réordonnancement des écritures — pour éviter ce genre de motif catastrophique, mais il y a des limites
    • Voici comment je le comprends
      Dans un SSD, la plus petite unité que l’on peut écrire est la page, et la plus petite unité que l’on peut effacer est un bloc composé de plusieurs pages
      Donc même si une écriture ne touche qu’un seul octet dans une page, le SSD ne peut pas effacer uniquement cet octet. Cela ne veut pas dire pour autant qu’il doit forcément effacer tout le bloc
      Le SSD peut effectuer une opération de type « lecture-modification-écriture » : lire dans le cache du SSD toute la page contenant l’octet à modifier, modifier seulement cet octet dans le cache de page, effacer un nouveau bloc vide, écrire la page modifiée depuis le cache dans ce nouveau bloc, puis mettre à jour la table de mapping FTL pour qu’elle pointe vers la page mise à jour dans le nouveau bloc
      Ainsi, même si un seul octet change, la page doit être réécrite. En revanche, on peut éviter d’effacer tout le bloc jusqu’à ce qu’un grand nombre de pages qu’il contient aient été modifiées
    • Pas exactement. L’idée logique selon laquelle une page vit à une adresse flash donnée ne correspond pas à la réalité
      Au fil des écritures, les pages se déplacent dans le périphérique physique. Le disque lui-même maintient une carte indiquant quelles adresses servent à quoi, leur état de santé, etc. C’est une sorte de stockage clairsemé
      Il existe aussi des commandes comme TRIM, ainsi que de la maintenance périodique et du garbage collection
      En pratique, lorsqu’on écrit sur un disque qui n’est pas plein, il cherche une page où placer les données, vérifie si elle contient déjà des données, effectue si nécessaire une lecture/modification/écriture, décide où écrire les données, puis les écrit. À cause du wear leveling, il y a de fortes chances qu’elles ne retournent pas à leur emplacement d’origine
      Il est vrai que le contrôleur effectue des étapes beaucoup plus complexes pour les performances. C’est pour cela qu’un disque neuf et vide fonctionne mieux pendant un temps, et qu’un vieux disque plein sans pages de réserve peut effectivement devenir plus lent
      Pour ajouter une source : j’ai été ingénieur principal sur un accélérateur flash mappé en mémoire avec cohérence de cache. Il permettait de mapper le disque très efficacement depuis l’espace utilisateur Linux, mais il a fini par céder, pendant un temps, au modèle de programmation « facile » où il ressemblait simplement à un disque dur de plus
    • C’est complètement faux. Même le contrôleur SSD le plus rudimentaire tente d’atténuer ce genre de situation
  • Cela m’a fait penser que mon patron chez Mojeek a probablement suivi un chemin très similaire. Cet article recoupe beaucoup de conversations passées
    Mojeek a été lancé en 2004 ; l’essentiel de sa structure a été construit par un seul développeur, qui a mis en place presque toute la recherche d’information et l’infrastructure
    Les contraintes financières et matérielles, les choix entre ID 32 bits et 64 bits, le sharding, la vitesse de mise à jour : tout cela me semble très familier
    Cela me rappelle aussi l’ancien « Google dance » de Google. À l’époque, les résultats de recherche étaient rafraîchis une fois par mois ; aujourd’hui, ils fluctuent tous les jours. Tout cela fait partie de l’évolution, et c’est agréable de voir Marginalia offrir un autre point de vue sur le Web au-delà de la big tech

  • Lecture agréable
    Beaucoup de gens considèrent l’optimisation comme une forme de magie noire profonde, mais la plupart du temps, c’est au contraire plus simple qu’une correction de bug ordinaire. Il suffit de traiter l’usage excessif des ressources comme un bug à part entière
    À mon avis, la plupart des bugs facilement reproductibles n’exigent pas de magie pour être corrigés. Si l’on peut titiller un bug, on peut généralement le classer, et même les rares défauts de conception deviennent en général assez évidents dès qu’on parvient à les reproduire
    Un logiciel dont personne n’a examiné les performances de façon critique est comme un logiciel contenant des centaines de bugs faciles à reproduire que personne n’a débogués. On peut en éliminer un par un pendant assez longtemps avant de tomber sur quelque chose de difficile
    Je pense que cette attitude est plutôt un vestige de l’époque où l’on ajustait l’adresse cible des branchements pour qu’elle arrive sous la tête du tambour au moment précis où le CPU avait besoin de l’instruction. Quand les ressources étaient extrêmement limitées, que tout était écrit à la main en assembleur, et que des emplacements mémoire globaux prenaient des significations différentes selon l’étape du programme, des gens déjà très intelligents avaient examiné les performances de façon critique ; il fallait donc trouver ce qu’ils n’avaient pas trouvé. C’est rare dans le code moderne

    • Je suis globalement d’accord, mais les bugs sont bien plus faciles à traquer avec une stratégie de diviser pour régner
      Si envoyer la requête X au service Y reproduit le bug, il suffit de réduire progressivement le cas de test jusqu’à trouver le coupable
      L’optimisation est souvent un problème d’architecture. Il arrive qu’on copie un buffer alors qu’on pourrait le réutiliser, mais ce genre de pistes s’épuise vite, et le profiler donne les informations nécessaires
      Les gros gains de performance viennent souvent du fait de changer tout le flux de données et d’en supprimer des pans importants, afin que le code accomplisse ce qu’il doit faire en aussi peu d’étapes que possible
  • Je me demande pourquoi il a choisi SQLite plutôt qu’un magasin clé-valeur. S’il veut seulement lire par ID et n’a pas besoin des autres colonnes, une base de données relationnelle semble superflue

    • Cela aurait aussi été possible. Il aurait pu créer une table temporaire dans MariaDB
      SQLite a l’avantage d’être un fichier unique. On peut donc le copier, le partager, et faire d’autres choses élégantes avec
  • J’aime cet autre exemple de contraintes qui engendrent l’innovation. L’innovation se trouve plus souvent dans les limites que dans l’abondance