36 points par GN⁺ 2026-03-19 | 1 commentaires | Partager sur WhatsApp
  • Règle 1 : il est impossible de prédire où un programme passera son temps. Les goulots d’étranglement apparaissent là où on ne les attend pas, donc n’essayez pas d’améliorer les performances tant qu’il n’est pas prouvé qu’il s’agit réellement d’un goulot d’étranglement
  • Règle 2 : la mesure d’abord. Le réglage des performances ne doit être fait qu’après mesure, et l’optimisation ne doit être envisagée que lorsqu’une partie du code domine clairement l’ensemble
  • Règle 3 : les algorithmes complexes sont lents pour les petits n. Les algorithmes complexes ont de grandes constantes ; tant que n ne grandit pas souvent, il faut utiliser une méthode simple. Et même si n grandit, il faut d’abord appliquer la règle 2
  • Règle 4 : les algorithmes complexes comportent plus de bugs et sont plus difficiles à implémenter. Il est préférable d’utiliser des algorithmes simples et des structures de données simples
  • Règle 5 : les données sont essentielles. Si l’on choisit la bonne structure de données et qu’on l’organise correctement, l’algorithme devient presque évident. Le cœur de la programmation n’est pas l’algorithme, mais la structure de données

Philosophie et citations associées

  • Les règles 1 et 2 ont le même sens que l’adage de Tony Hoare : « l’optimisation prématurée est la racine de tous les maux »
  • Ken Thompson a réinterprété les règles 3 et 4 en « en cas de doute, utilisez la méthode simple (Brute Force) »
  • Les règles 3 et 4 sont un exemple de la philosophie de conception KISS (Keep It Simple, Stupid)
  • La règle 5 avait déjà été évoquée par Fred Brooks dans The Mythical Man-Month,
    souvent résumée par « écrire un code simple en utilisant des objets intelligents »

1 commentaires

 
GN⁺ 2026-03-19
Réactions sur Hacker News
  • Cela rappelle la conférence de Jonathan Blow
    Il l’abordait sous l’angle de la productivité. Au début du développement de Braid, il a implémenté presque tout avec de simples tableaux, puis n’a modifié les choses qu’au moment où des goulets d’étranglement apparaissaient
    Sa phrase « ce qui compte plus que la vitesse ou la mémoire, c’est le temps de vie humaine nécessaire pour implémenter un programme » était marquante

    • Les jeux traitent en boucle un grand nombre d’objets similaires à plus de 60 images par seconde, donc une structure basée sur des tableaux est un choix par défaut raisonnable
    • En développement de jeux, il faut rendre une frame en 16 ms, donc les tableaux de taille fixe et la recherche linéaire sont des motifs fréquents. C’est un choix structurel pour éviter l’imprévisibilité de l’allocation dynamique
    • Cette perspective vaut aussi pour le développement général hors jeu. Nous travaillons tous avec des contraintes de délais et de coûts, donc le temps d’ingénierie est lui-même un coût
    • Il faut toutefois être prudent avant d’étendre directement les leçons du jeu à la programmation en général. Le jeu privilégie le code à usage spécifique plutôt que la réutilisation, alors que les logiciels généraux sont davantage centrés sur les données
    • Pour ma part, je suis du genre à commencer avec une table de hachage plutôt qu’un tableau
  • Si l’on prend la Rule 1 au sérieux, les Rules 3 à 5 en découlent naturellement
    Si l’on admet qu’il est impossible de prédire les goulets d’étranglement, alors écrire du code simple et mesurer devient la seule stratégie rationnelle
    En pratique, l’échec le plus fréquent n’est pas l’optimisation prématurée, mais l’abstraction prématurée. On crée des couches complexes pour une flexibilité inutile, et cela finit par alourdir le coût de maintenance

    • Dans l’équipe, on cite souvent cette idée : « l’abstraction doit émerger naturellement, pas être conçue à l’avance »
    • L’abstraction prématurée gaspille du temps de développement, augmente la dette technique et accroît le risque de bugs. Elle apparaît souvent au nom de la préparation à de “futurs problèmes”
    • Comme lecture connexe, on peut consulter le texte de Philip Wadler
    • Pour ma part, j’accorde plus d’importance à la lisibilité et à la maintenabilité qu’aux performances. Pour moi, c’est donc la Rule 4 qui est fondamentale, et la Rule 1 en est la conséquence
    • J’ai déjà vu des cas où des fichiers de configuration complexes avaient été trop fragmentés. Au final, 8 simples fichiers YAML suffisaient
  • Dans les années 90, j’ai dû implémenter à 2 heures du matin une fonction de recherche dans un jeu de données
    J’étais fatigué, alors je l’ai faite en recherche linéaire en me disant que je corrigerais plus tard, mais en réalité cela n’a représenté que 6 secondes d’écart sur un test de 4 heures
    J’ai fini par le corriger, mais il n’y avait pas de différence significative

    • Pour de petites valeurs de n, la recherche linéaire peut même être plus rapide
    • En revanche, un algorithme en O(n²) comporte le risque d’« être déployé, puis exploser en production tôt ou tard »
  • Je suis totalement d’accord avec la Rule 5
    Plus le problème est difficile, plus il se résout par des améliorations itératives des structures de données et des API. Quand la structure est bien pensée, le flux de contrôle devient naturel
    Les LLM sont faibles sur ce type de réflexion structurelle. Ils proposent facilement des flux de contrôle complexes, mais sont mauvais pour concevoir des structures de données composables

    • D’après mon expérience, la Rule 5 est en réalité la vraie Rule 1. Il y a cette formule : « le code embrouille, mais si on montre le schéma de base de données, tout devient clair »
    • Dans les services distribués, la Rule 5 est souvent ignorée. Au lieu de multiplier les appels HTTP et DB, une structure capable de tout traiter en un seul appel est plus efficace
  • Je viens de l’électrotechnique (E.E.), et la Rule 3 m’a évité de gros problèmes au début de ma carrière
    Mais plus tard, en passant à des systèmes de grande taille, n a augmenté et la complexité est devenue réellement importante
    Le “big iron” de l’époque de Rob Pike ressemblait aux environnements embarqués d’aujourd’hui

    • Je suis en désaccord partiel avec la Rule 3. Sur de petites entrées, ce n’est pas grave, mais pour de grandes entrées, les performances en grand O comptent.
      Si deux algorithmes ont une difficulté d’implémentation comparable, je choisis celui qui est plus rapide sur de grandes entrées
      Article lié : Less Than Quadratic
    • Il faut interpréter “fancy” en fonction du domaine du problème. Si n est petit, une approche simple est préférable, mais si n est grand, des algorithmes avancés deviennent indispensables
      Souvent, des gens choisissent une approche O(n²) trop simpliste et finissent par exploser en production
    • Mon père utilisait volontiers des lookup tables dès l’époque du Fortran. C’est une méthode classique d’optimisation pour réduire les calculs répétés
  • Je trouve les règles de Pike meilleures que les maximes habituelles
    Des phrases comme « l’optimisation prématurée est la racine de tous les maux » perdent facilement leur contexte et se prêtent aux malentendus
    La version de Pike est claire et difficile à détourner
    Il existait une vieille formule disant que « la Rule 5 se résume à laisser du code stupide utiliser des objets intelligents »,
    mais à l’époque de l’orienté objet, cela a au contraire dérivé en croyance erronée masquant la complexité

    • Il est important de conserver le chaînon de la pensée historique
    • L’expression « clickbait mental des maximes classiques » me semble être une sorte de métaphore bien trouvée
  • Après plus de dix ans sur la même base de code, j’ai totalement intériorisé les règles de Pike
    Respecter les principes KISS/DRY et conserver des technologies éprouvées plutôt que des technologies à la mode s’est révélé plus stable sur le long terme
    En pratique, le document de principes de développement de notre équipe dit presque la même chose que les règles de Pike

  • Au début des années 1990, à l’époque du C++, j’ai remplacé une liste doublement chaînée par une simple réallocation de tableau,
    et non seulement les bugs ont disparu, mais c’était même plus rapide.
    J’ai appris qu’effectuer moins souvent les opérations coûteuses est une bonne stratégie

  • Il est intéressant de comparer la règle « ne faites pas de tuning sans mesurer » avec Latency Numbers Every Programmer Should Know de Jeff Dean
    Dean dit qu’avec des connaissances préalables, on peut prédire les performances
    Au fond, les deux positions peuvent être conciliées : au moment de la conception, on choisit intuitivement une structure rapide, puis après l’implémentation, on affine sur la base de mesures réelles

    • Le code vraiment rapide utilise les deux approches. Dès la conception, il tient compte de l’efficacité cache, puis élimine les goulets d’étranglement via le profiling
    • Les chiffres de latence ne donnent que la borne théorique d’un algorithme ; les performances réelles dépendent de l’implémentation et de l’environnement d’exécution
    • Ce que l’« optimisation prématurée » interdit, c’est le micro-tuning local de type bidouille. Penser à la vitesse dans la conception globale est parfaitement normal
  • Les Rules 1 et 2 ne sont absolues que lorsqu’on traite un problème nouveau
    Quand on construit des systèmes de manière répétée dans le même domaine, on peut prédire à l’avance les points de blocage
    Un développeur expérimenté peut avoir une intuition approximative des performances avant même la conception

    • Moi aussi, dans la plupart des cas, j’ai correctement prédit les goulets d’étranglement. Il m’est souvent arrivé de changer d’approche après des tests de performance préalables
    • Mais en 30 ans d’expérience, j’ai constaté que même si l’intuition sur l’apparition d’un goulet est juste, l’endroit exact et le moment précis restent imprévisibles
    • Il y avait aussi la blague « qu’est-ce que Rob Pike peut bien savoir », mais c’est quelqu’un qui a créé Unix et Go. Ses règles ont leurs raisons