Contacter l'assistance

Nous répondons par e-mail, en général sous deux jours.

Pour prévenir les abus, Google reCAPTCHA vérifie cet envoi ; des données sont transmises à Google. Le script n'est chargé qu'à l'ouverture de ce formulaire.

← Tous les articles

Quand un cache grandit dans le mauvais sens

Dans le dossier de cache de ce service il y a quatre petits fichiers. Le plus gros fait 35 octets. Ensemble ils contiennent trois numéros de compteur, et ils sont lus à chaque requête de compteur.

Ils existent pour que le chemin de comptage n'ait pas à poser à la base quatre questions auxquelles il répond presque toujours « non ». Ce compteur exclut-il les visites de son propre propriétaire ? Compte-t-il les clics sortants ? Suit-il les parcours dans le site ? Se recharge-t-il tout seul ? Pour plus de 99 % des compteurs chaque réponse est non, et un fichier contenant la poignée de numéros où elle est oui coûte moins cher à consulter que quatre requêtes indexées.

Il coûte moins cher. C'est aussi le genre de bon marché qui se retourne.

2 10 100 1 000 10 000 100 000 les 2 218 compteurs actifs : 0,43 ms le fichier : 0,02 ms à 3 numéros, 21,4 ms à 100 000 une requête indexée : 0,16 ms à toute taille

Ce qui a été mesuré

La même question — « ce compteur est-il dans la liste ? » — posée de deux façons, à six tailles de liste. La voie du fichier : le lire, décoder le JSON, chercher le numéro. La voie de la base : une requête préparée contre une colonne indexée. Deux mille répétitions chacune, cinq tours, médiane retenue.

À la taille d'aujourd'hui le fichier gagne d'un facteur huit : 0,0202 milliseconde contre 0,1630. À mille numéros ils sont à égalité. À dix mille le fichier coûte douze fois plus, et à cent mille il coûte 135 fois plus, parce qu'il s'agit alors de 578 kilooctets à lire et à analyser à chaque visite.

La ligne de la base ne bouge pas. 0,16 milliseconde à deux lignes et 0,16 milliseconde à cent mille : c'est à cela que sert un index, et on oublie facilement tout le travail caché derrière une ligne aussi ennuyeuse.

La partie gênante

Le croisement se situe entre 100 et 1 000 numéros. Ce service compte 2 218 compteurs ayant eu du trafic ces trente derniers jours.

Si l'exclusion était donc un succès — si tous ceux qui ont un compteur activaient « ne compte pas mes propres visites » — le fichier contiendrait 2 218 numéros, pèserait 11 kilooctets et coûterait 0,43 milliseconde par visite au lieu de 0,02. Sur les 18 423 visites d'hier, cela fait huit secondes de travail par jour pour éviter une requête qui en aurait pris trois.

L'optimisation est la plus rapide quand la fonctionnalité est la moins utilisée. Elle ne se dégrade pas progressivement sous la charge, comme une requête lente. Elle se dégrade avec l'adoption, qui est le seul axe que personne ne surveille, puisqu'une adoption qui monte est censée être la bonne nouvelle.

Pourquoi cela reste

Parce que c'est juste aujourd'hui, et « juste aujourd'hui » a le droit d'être la raison de quelque chose, tant que quelqu'un a écrit quand cela cesse d'être vrai.

Trois numéros dans trois fichiers. Huit fois moins cher que l'autre solution, sur une machine où le chemin de comptage est la seule chose qui doive être rapide. Le remplacer maintenant par la requête qu'il bat donnerait un système moins bon, justifié par une hypothèse.

Ce qui manque, c'est le fil déclencheur, pas la réécriture. Le fichier est de toute façon écrit depuis la base, par le code qui change un réglage — c'est l'endroit naturel pour remarquer que la liste a dépassé quelques centaines d'entrées, et pour le dire. Un cache avec un plafond écrit est une décision. Un cache sans plafond est un pari que personne n'a accepté.

La forme générale

Ce n'est pas un argument contre le cache dans un fichier. C'est un argument pour savoir dans quel sens votre cache grandit.

La plupart des caches s'améliorent sous la charge : plus de requêtes, plus de succès, meilleur ratio. Celui-ci est de l'autre espèce. Son coût par requête dépend de la quantité qu'il contient, et ce qu'il contient grandit avec ce que le service cherche à encourager. Chaque lecture paie pour chaque entrée, y compris les 2 215 qui n'ont rien à voir avec le visiteur compté à l'instant.

La question à poser à toute table de correspondance tenue en mémoire ou dans un fichier n'est pas « à quelle vitesse va-t-elle » mais « qu'est-ce qui la fait grandir, et que se passe-t-il quand cette chose réussit ». Si la réponse est « elle ralentit », la limite de taille appartient au code, à côté de ce qui écrit le fichier, le jour où on le construit.

Publicité