← Articles
technique

Trois jours de horosvec : chronique d'une campagne de mesure

2026-07-09 17:06:55 · 01960e00-0001-7000-8000-000000000001

La bibliothèque horosvec — un index vectoriel approché en Go pur, persisté dans un fichier SQLite — a déjà été présentée ici (horosvec, un index vectoriel ANN en Go pur). Cet article-ci raconte la campagne de trois jours, du 7 au 9 juillet 2026, qui l'a menée d'un composant interne jamais éprouvé à grande échelle jusqu'à l'indexation des 26,7 millions d'items de Hacker News et à un banc comparatif contre hnswlib et sqlite-vec. Le fil conducteur n'est pas la liste des chiffres favorables : ce sont les erreurs de mesure commises en route, et les détecteurs qui les ont démasquées. Presque chaque nombre publié à la fin a d'abord été mesuré faux.

Le point de départ : un chemin de code que la production n'avait jamais emprunté

Le fait fondateur de la campagne tient en une phrase : en plusieurs mois de production, le chemin de recherche approchée n'avait jamais été exercé. Le plus gros index en service comptait 5 632 vecteurs, alors que le seuil de bascule vers la recherche exacte est de 50 000 : toutes les requêtes de production empruntaient le chemin exact, parfait par construction, et les défauts du graphe approché dormaient dans un code que rien n'avait jamais touché. Ce que la production n'exerce pas reste cassé ; un banc comparatif est un instrument de découverte, pas un tableau d'affichage.

Une échelle de bancs — 14 000 vecteurs réels, puis 100 000, puis un million — a révélé à chaque palier un défaut invisible au palier précédent : une fonction de distance quantifiée plus coûteuse que le calcul exact qu'elle devait éviter, un paramètre de largeur de recherche purement décoratif masqué par le rappel parfait des petits corpus, une rotation aléatoire manquante que seul un jeu de données difficile comme SIFT rendait nécessaire (rappel de 0,955 à 0,987). Puis vint l'échelle réelle : les 28,7 millions de lignes du corpus public Hacker News, ramenées à 26 691 317 items éligibles, plongés en vecteurs de 512 dimensions en 6 h 40 sur un seul GPU, le graphe construit par cuVS/CAGRA en 17,1 minutes et importé dans horosvec en 21,7 minutes. L'index validé affichait un recouvrement de 99 % sur les dix premiers résultats face à une recherche exacte exhaustive.

C'est là que commencent les trois erreurs qui structurent ce récit.

Première erreur : le disque qui mentait par omission

Première mesure de latence de bout en bout sur l'index de 26,7 millions de vecteurs : 2,9 secondes par requête en médiane. Une reprise « à chaud » six heures plus tard : 2,7 secondes. C'est ce second chiffre qui aurait dû alerter immédiatement — une exécution à chaud qui n'est pas plus rapide que l'exécution à froid n'est pas à chaud. Soit le cache a été vidé entre-temps, soit le goulot n'est pas où l'on croit.

Le jeu de travail — 27 Go de vecteurs en demi-précision plus 19 Go d'index SQLite — résidait sur un disque rotationnel d'archivage de 18 To : chaque défaut de page pendant le reclassement des candidats payait un déplacement mécanique de tête de lecture, et le cache avait été évincé entre les deux exécutions. Le même index et les mêmes requêtes, déplacés sur un disque NVMe après vérification d'intégrité octet par octet, ont rendu 27,6 ms à froid et 7,8 ms à chaud. Une erreur d'un facteur 100 à 370, entièrement signée par le support de stockage : l'algorithme était innocent depuis le début, et le chiffre « environ 3 secondes » avait failli être consigné comme son profil mesuré. La règle qui en sort : toute mesure de latence porte son support de stockage aussi silencieusement que son jeu de données ; il faut nommer le support dans chaque nombre publié.

Deuxième erreur : le banc qui mesurait la mauvaise machine

Le banc comparatif à trois moteurs a ensuite produit deux constats accablants contre horosvec lui-même : un effondrement de débit d'un facteur 5,7 au-delà d'un certain réglage de largeur de recherche, là où hnswlib ne perdait qu'un facteur 1,8 ; et une montée en concurrence morte, quand hnswlib passait proprement à l'échelle. Les deux constats furent consignés — puis démontés méthodiquement.

Le premier détecteur fut la reproduction à échelle réduite : refaire la mesure sur 300 000 vecteurs au lieu d'un million. La falaise de débit s'est déplacée avec la taille du corpus — or un défaut qui bouge avec l'échelle est un régime de ressources, pas un coût algorithmique. Le second détecteur fut le profil d'exécution, filtré sur la seule fenêtre de requêtes : 41 % du temps en ramasse-miettes, 22 % en balayage mémoire, 21,6 % dans le verrou du pilote SQL. Le chemin de recherche faisait du SQL, ce que la configuration de production ne fait jamais.

Une recherche textuelle plus tard, le coupable était trouvé : le harnais n'activait la configuration de production — le reclassement lu depuis le fichier de vecteurs projeté en mémoire — que par une variable d'environnement optionnelle et silencieuse, restée non définie. Toutes les courbes horosvec du banc avaient mesuré le chemin de repli, où chaque candidat est relu ligne à ligne depuis la base : une tempête d'allocations derrière un verrou global. La reprise avec la bonne configuration a dissous les deux constats : le débit à 32 clients a été multiplié par 56 (de 1 581 à 88 218 requêtes par seconde à un point de mesure). Deux règles en sortent : un harnais qui choisit sa configuration par une option silencieuse ment par défaut — le mode mesuré appartient au fichier de résultats ; et tout constat porté contre un système doit nommer le chemin de code qu'il a réellement mesuré. Les courbes du mode de repli restent d'ailleurs publiées : ce sont de vraies mesures d'un vrai mode, simplement pas celui qui est livré.

Troisième erreur : les constantes forgées de tête

Deux fautes plus petites, de la même famille. Un oracle de taille de fichier, calculé mentalement au moment du plan, était faux de 256 000 octets — le fichier était juste, le plan était faux. Et un plancher de rappel fixé à 0,90, mesuré sur des données synthétiques uniformes, s'est révélé inatteignable sur des grappes gaussiennes serrées (0,678, limite intrinsèque de la quantification à un bit en 128 dimensions). Les seuils héritent de la distribution sur laquelle ils ont été mesurés, et les nombres de référence se calculent par script, jamais de tête.

Les chiffres finals, avec leurs périmètres et leurs défaites

Voici où les nombres ont atterri, une fois toutes les erreurs corrigées — chaque chiffre avec son périmètre exact, défaites comprises. Sur le corpus réel d'un million de vecteurs en 512 dimensions (textes Hacker News), sous 32 clients concurrents, horosvec soutient environ 1,9 fois le débit de hnswlib à chaque point de la courbe, avec un rappel égal ou supérieur :

Largeur (ef) horosvec (req/s) hnswlib (req/s) rappel horosvec / hnswlib
64 39 599 20 501 0,9468 / 0,9138
256 11 975 6 356 0,9892 / 0,9812
512 6 582 3 423 0,9938 / 0,9892

Les défaites, assumées et publiées : en mono-client sur le même corpus, le cœur C++ de hnswlib est environ deux fois plus rapide par fil d'exécution — horosvec ne gagne qu'en parallélisant mieux. Et sur SIFT, corpus classique en 128 dimensions, hnswlib délivre environ cinq fois le débit à rappel équivalent : un bit par dimension manque d'information à si basse dimension, faiblesse structurelle documentée et inscrite à la feuille de route. sqlite-vec, recherche exacte, sert de témoin de rappel du harnais et reste un bon choix sous 50 000 vecteurs, mais n'est pas un concurrent approché à grande échelle. L'index complet de Hacker News, lui, répond en 7,8 ms de latence médiane, sans reconstruction à l'ouverture.

Ce qui reste quand les chiffres sont partis

La conclusion de ces trois jours n'est pas le facteur 1,9. C'est que chaque détecteur qui a sauvé la campagne coûte presque rien : une exécution à chaud comparée à froid, une reproduction à échelle réduite, un profil de quelques minutes, un recalcul par script. Les erreurs interceptées — un facteur 100 sur la latence, un facteur 56 sur le débit — auraient toutes produit des résultats parfaitement plausibles, archivés, et faux. La discipline de mesure vaut plus que les chiffres favorables qu'elle finit par produire.

Pour aller plus loin

Une démonstration publique de recherche sur l'index Hacker News complet, à l'adresse horosvec.hazyhaar.fr, est de mise en ligne imminente.

goannbenchmarkmesureretour-d-experience