Comment comparer correctement la vitesse de différentes versions d'un programme sous Windows

· Mis à jour le: · · Windows, Benchmark, Performance, Profilage, Gestion de l'alimentation

Vous voulez comparer la version A et la version B d’un programme sous Windows. La pire chose à faire dans ce cas est d’exécuter chacune une seule fois sur la même machine et de déclarer : « B semble environ 8 % plus rapide. »

Ces 8 % correspondent peut-être réellement à la différence de code. Mais en pratique, c’est souvent l’un de ces facteurs — le mode d’alimentation, le plan d’alimentation, la chaleur, les mises à jour en arrière-plan, l’indexation de recherche, les analyses antivirus, l’affinité, l’ordre d’exécution ou l’état du cache — qui est en cause : c’est le grand classique du benchmark sous Windows. Un monde assez ingrat, merci.

Cet article rassemble une méthode pour comparer la vitesse d’exécution de différentes versions d’un programme sous Windows, en se rapprochant autant que possible de la seule différence de code. Il vise principalement Windows 11, mais l’essentiel — powercfg, start, etc. — fonctionne de la même façon sous Windows 10.

D’abord, la conclusion

En fin de compte, les astuces pour améliorer la reproductibilité se résument à ces six points.

  1. Décider d’abord « ce que l’on veut comparer » Selon que l’on veut voir la différence de code ou l’expérience utilisateur réelle, les conditions d’environnement à aligner changent.

  2. Consigner le mode d’alimentation et le plan d’alimentation comme deux choses distinctes Sous Windows, traiter ce point avec négligence transforme facilement la comparaison en une comparaison des politiques d’économie d’énergie de l’OS.

  3. Séparer la première exécution à froid (cold) du régime stable une fois échauffé (warm) Il n’est pas rare que seule la première exécution soit rapide, ou que seule la seconde moitié soit lente.

  4. Alterner les exécutions, A→B→A→B Exécuter d’abord toute la version A puis toute la version B fait subir le déséquilibre de la chaleur et de l’état de l’arrière-plan.

  5. Regarder la médiane et la dispersion, pas seulement la moyenne Une seule valeur aberrante peut tout faire basculer. La moyenne est plus fragile qu’on ne le pense.

  6. Si la différence est faible, creuser jusqu’à la cause avec ETW / WPR Discuter à partir d’une simple impression finit généralement en pugilat dans le brouillard.

Décider d’abord ce que l’on veut comparer

« Comparaison de vitesse » semble désigner une seule chose, mais il en existe en réalité deux sortes.

1. Une comparaison pour voir la différence de code

C’est une comparaison qui vise à savoir si l’implémentation elle-même est devenue plus rapide, à la suite d’un changement d’algorithme, d’une modification de structure de données, d’une optimisation du compilateur, d’une mise à jour du runtime, etc.

Dans ce cas, on réduit autant que possible le bruit environnemental. Une session dédiée au benchmark, un mode d’alimentation fixé, les notifications coupées, l’indexation de recherche et la synchronisation suspendues, et, si nécessaire, on va jusqu’à un clean boot.

2. Une comparaison pour voir l’expérience utilisateur réelle

C’est une comparaison qui vise à connaître la vitesse que les utilisateurs ressentiront réellement, une fois le programme distribué, sur leur Windows habituel.

Dans ce cas, il ne faut pas effacer tout le bruit qui existe réellement. Comparer dans un « environnement quotidien plausible », incluant la synchronisation OneDrive, Defender, les notifications et les réglages d’alimentation habituels, donne un résultat plus proche de la réalité.

Mélanger ces deux approches tord les conclusions. Des situations comme « 12 % plus rapide en labo, mais dans la marge d’erreur en conditions réelles » ou « plus rapide en conditions réelles, mais inchangé en temps CPU » se produisent couramment.

Les principales causes de variation des résultats sous Windows

Commençons par dresser une liste sommaire de ce qui fait varier les résultats.

Couche Facteur de variation Exemple typique
Matériel CPU / GPU, mémoire, SSD, refroidissement Finesse d’un portable, présence ou non d’un socle de refroidissement
Firmware BIOS / UEFI, contrôles OEM Politiques d’économie d’énergie, contrôle des ventilateurs
OS Build Windows, pilotes, état des mises à jour Le même PC se comporte différemment après une mise à jour
Alimentation Secteur / batterie, mode d’alimentation, plan d’alimentation Sur batterie, c’est un autre monde
Chaleur Température de la pièce, ventilateurs, charge précédente Turbo uniquement au premier essai, ralentissement ensuite
Arrière-plan Update, Defender, synchronisation, notifications Une analyse ou une synchronisation se lance pendant l’exécution
Ordonnancement Priorité, affinité, NUMA Le placement des CPU varie selon la machine
Données / cache Cache OS, cache applicatif Lent uniquement la première fois, rapide seulement à partir de la deuxième exécution
Conditions de build Debug / Release, PGO, journalisation activée ou non On compare en réalité des choses différentes

En résumé, même « la même machine Windows » constitue une expérience différente si les conditions ne sont pas alignées.

Traiter séparément le mode d’alimentation et le plan d’alimentation

Ce point est assez important.

Windows possède le mode d’alimentation de l’application Paramètres et le plan d’alimentation traditionnel (le schéma d’alimentation visible via powercfg). Ils se ressemblent, si bien qu’on a tendance à les confondre, mais les traiter à la légère fait sombrer la comparaison dans la confusion.

Dans l’application Paramètres de Windows, on choisit le mode d’alimentation depuis Système > Alimentation et batterie. La documentation Microsoft indique que l’on peut basculer entre Best power efficiency (Meilleure efficacité énergétique), Balanced (Équilibré) et Best performance (Meilleures performances) séparément pour Sur secteur / Sur batterie. De plus, changer le mode d’alimentation influence aussi, en coulisses, les réglages liés à l’alimentation et le comportement du PPM (Processor Power Management). Autrement dit, ce seul réglage peut changer la politique de Core Parking et de mise à l’échelle des performances.

Le plan d’alimentation, quant à lui, est le schéma d’alimentation traditionnel : Balanced (Équilibré), High performance (Performances élevées), etc. On peut le vérifier avec powercfg /list ou powercfg /getactivescheme.

Ce qui complique les choses ici, c’est que Windows possède à la fois une surcouche de mode d’alimentation et un plan d’alimentation. Aussi, consignez au minimum les éléments suivants avec vos résultats de benchmark.

  • Secteur ou batterie
  • Quel mode d’alimentation
  • Quel plan d’alimentation actif

Un résultat de benchmark qui n’indique pas ces trois éléments est assez pénible à relire plus tard.

Les conditions d’alimentation à fixer en premier

  1. Toujours comparer les ordinateurs portables sur secteur Le fonctionnement sur batterie introduit facilement des limitations non désirées.

  2. Fixer le mode d’alimentation Pour un usage de benchmark, commencez par essayer Best performance.

  3. Consigner le plan d’alimentation actif Enregistrez la valeur actuelle avec powercfg.

powercfg /list
powercfg /getactivescheme
  1. Passer à Performances élevées si nécessaire
# Balanced
powercfg /setactive 381b4222-f694-41f0-9685-ff5bb260df2e

# High performance
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

L’absence de « Performances élevées » n’a rien d’anormal

C’est aussi un piège classique. La documentation Microsoft indique que sur les appareils compatibles Modern Standby, seul le plan Équilibré, ou un plan qui en dérive, est autorisé. Donc, plutôt que de se dire « Performances élevées est introuvable, c’est cassé ? », il est possible que ce soit ainsi que cet appareil a été conçu.

Microsoft indique par ailleurs que si le mode d’alimentation ne peut pas être modifié, un plan d’alimentation personnalisé (custom power plan) est peut-être sélectionné, et conseille d’essayer d’abord de choisir Équilibré. Quand l’interface du mode d’alimentation ne réagit pas, c’est la première chose à suspecter.

Éliminer le bruit en arrière-plan

Windows est travailleur. Même quand on veut faire un benchmark tranquille, il s’active en coulisses pour nous rendre toutes sortes de services.

D’abord, redémarrer et attendre que ça se calme

Après avoir changé les réglages, redémarrez une fois, et n’exécutez rien immédiatement après la connexion : attendez quelques minutes. Juste après le démarrage, les mises à jour, l’indexation, la synchronisation, Defender et divers processus résidents s’agitent encore.

Pour une comparaison sérieuse, utiliser un clean boot

Microsoft décrit une procédure permettant, via un clean boot, de réduire la configuration au démarrage minimal : arrêter les services non Microsoft dans msconfig et désactiver les applications de démarrage dans le Gestionnaire des tâches.

C’est très efficace pour réduire le bruit. Cela dit, cela s’éloigne de l’environnement d’utilisation quotidien, donc c’est plus adapté à une « comparaison en labo destinée à voir la différence de code ».

Faire taire les notifications

Les bannières de notification de Windows paraissent anodines, mais gênent étonnamment. Au-delà de la gêne visuelle, elles peuvent modifier le moment d’exécution, le focus et l’activité des applications en arrière-plan.

Activez manuellement Ne pas déranger, ou coupez au moins les notifications pendant le benchmark.

Limiter l’indexation de recherche et la synchronisation

Si la cible du benchmark lit un grand nombre de fichiers, écrit une grande quantité de résultats, ou reconstruit plusieurs fois l’arborescence source, l’indexation de recherche et la synchronisation cloud pèsent discrètement.

  • Exclure le répertoire de benchmark de l’indexation de recherche
  • Arrêter la synchronisation d’OneDrive / Dropbox / Google Drive, etc.
  • Fermer le navigateur, Teams, Discord, Slack

Rien de spectaculaire ici, mais quand ça compte, ça compte vraiment.

Une comparaison qui n’aligne pas la chaleur compare surtout la chaleur

Un CPU ou un GPU se comporte comme une créature différente selon qu’il est froid ou échauffé. C’est particulièrement marqué sur les ordinateurs portables, les mini PC fins et les petits ordinateurs de bureau.

Règles à respecter

  • Garder la température de la pièce aussi constante que possible
  • Fixer la façon dont le portable est posé
  • Fixer l’adaptateur secteur, le dock et la configuration des écrans externes
  • Ne pas effectuer de travail lourd juste avant le benchmark
  • Mesurer séparément la première exécution et le régime stable

Alterner l’ordre d’exécution

Évitez d’exécuter A dix fois puis B dix fois. Le déséquilibre lié à la chaleur, au cache et à l’activité en arrière-plan s’accumulerait.

Voici les approches recommandées.

  • A B A B A B ...
  • A B B A A B B A ...
  • Générer un ordre aléatoire à l’avance et l’exécuter dans cet ordre

Ce que l’on mesure change le sens de « rapide »

Réduire « rapide » à un seul chiffre finit généralement en accident. Voici les trois indicateurs représentatifs à surveiller sous Windows.

1. Le temps wall-clock

C’est le temps que l’utilisateur attend. C’est la valeur la plus proche du ressenti de bout en bout, donc c’est la première à regarder.

Sous Windows, QueryPerformanceCounter (QPC) permet d’obtenir un horodatage à haute résolution. En code managé, la classe Stopwatch est le choix standard. Se contenter d’observer des millisecondes avec DateTime.Now est, avouons-le, un peu imprudent.

2. Le temps CPU (temps utilisateur + noyau)

C’est le temps pendant lequel le processus a réellement utilisé le CPU, obtenu via GetProcessTimes.

C’est utile pour observer l’efficacité de calcul. Par exemple, si le temps wall-clock s’est amélioré mais que le temps CPU n’a pas changé, le cache, les E/S, le temps d’attente ou l’ordonnancement pourraient être en cause.

3. Le nombre de cycles (cycles CPU)

QueryProcessCycleTime permet d’obtenir le nombre de cycles CPU pour l’ensemble du processus.

C’est aussi un indicateur du travail CPU, mais il révèle une facette différente du wall-clock. Il est particulièrement utile quand on veut savoir si « le temps d’attente est identique, mais la partie calcul est devenue plus légère ».

Priorité, affinité et NUMA : les derniers recours

Ces réglages peuvent avoir un effet. Mais les toucher dès le départ, simplement parce qu’ils marchent, crée facilement un phénomène différent.

D’abord, mesurer normalement

Si un écart apparaît dans l’état par défaut, cet écart a de la valeur en soi. Introduire d’emblée /high ou /affinity revient à importer des « conditions qui ne se produisent pas sur un Windows réel ».

Si vous les utilisez, précisez l’objectif

  • /high : vous voulez réduire les perturbations causées par d’autres processus
  • /affinity : vous voulez fixer le placement des CPU pour la comparaison
  • Contrôle NUMA : vous voulez aligner jusqu’à la localité mémoire sur une grosse machine

La commande start de Windows permet de lancer un programme avec une classe de priorité et un masque d’affinité.

start "" /high /wait myapp.exe --bench case1.json
start "" /affinity F /high /wait myapp.exe --bench case1.json

Mais évitez /realtime

/realtime est disponible, mais il vaut mieux ne pas l’utiliser. Il tend à générer un nouvel accident plutôt qu’à supprimer du bruit.

Une procédure de mesure recommandée

En tenant compte de tout ce qui précède, voici une procédure facile à appliquer en pratique.

Procédure de comparaison orientée labo

  1. Fixer les cibles de comparaison
    • hash de commit / numéro de build
    • version du compilateur / du runtime
    • Debug / Release
    • présence ou non de journalisation, d’assertions, de traçage
  2. Fixer les conditions de la machine
    • build Windows
    • version du BIOS / UEFI
    • version du pilote
    • connexion secteur
    • température de la pièce, mode d’installation
  3. Fixer les conditions d’alimentation
    • décider du mode d’alimentation
    • consigner le plan d’alimentation actif
  4. Redémarrer
  5. Attendre quelques minutes avant le benchmark
  6. Clean boot si nécessaire
  7. Inclure un warm-up
  8. Alterner les exécutions de A / B
  9. Assurer un nombre suffisant de répétitions
  10. Conserver la médiane, le minimum, le maximum et le p95
  11. Sauvegarder les données brutes
  12. Capturer ETW / WPR si la différence est faible

Éléments à consigner qui aident plus tard

Dans le CSV ou le JSON du benchmark, conserver au moins les éléments suivants est précieux.

timestamp,version,scenario,elapsed_ms,user_ms,kernel_ms,cycles,power_mode,power_plan,ac_or_dc,room_temp_c,notes

Si possible, il est également utile d’ajouter les éléments suivants.

cpu_package_temp_start_c,cpu_package_temp_end_c,affinity_mask,priority_class,windows_build,driver_version

Pour un benchmark, pouvoir l’interpréter plus tard compte parfois plus que la mesure elle-même.

Regarder la médiane et la distribution, pas seulement la moyenne

La moyenne est pratique, mais elle se casse facilement dans les benchmarks Windows. Il suffit que Defender se déclenche une seule fois, qu’une notification apparaisse, ou qu’un autre processus sollicite fortement le SSD, pour que la moyenne soit faussée.

Voici la combinaison recommandée.

  • Médiane : à regarder en premier
  • p95 / p99 : pour voir si la queue de distribution s’est dégradée
  • min / max : pour voir l’ampleur des écarts
  • Boîtes à moustaches ou nuages de points : utiles quand la différence est faible

Comment lire un écart quand il apparaît

L’interprétation des résultats devient plus claire lorsqu’on regarde les combinaisons.

Seul le wall-clock est plus rapide

Cela peut venir d’une amélioration des E/S, du temps d’attente, du cache ou de l’ordonnancement.

Le temps CPU et les cycles ont tous deux baissé

Il est probable que l’implémentation elle-même soit devenue plus légère.

Seule la première exécution est lente / rapide

C’est la différence entre cold et warm. Suspectez le démarrage, l’initialisation, la génération de cache ou le JIT.

Ça ralentit à mesure que les exécutions s’accumulent

Suspectez la chaleur, le throttling, la pression mémoire ou l’activité en arrière-plan.

Creuser jusqu’au « pourquoi c’est plus rapide » avec ETW / WPR

Quand la différence est faible, ou que la raison reste illisible, la voie royale consiste à passer aux outils ETW (Event Tracing for Windows) de Windows.

Le Windows Performance Recorder (WPR) de Microsoft est un outil d’enregistrement basé sur ETW, inclus dans le Windows ADK. Il permet de capturer d’un coup le CPU, les E/S, les changements de contexte, les défauts de page, etc.

Voici le minimum.

wpr -start CPU -filemode

REM Exécuter le benchmark ici

wpr -stop trace.etl

Arrivé à ce stade, au lieu de dire simplement « B est 3 % plus rapide », vous pouvez expliquer avec des raisons, du type : « B a moins d’attente sur les locks et un ready time plus bas. » « A ouvre plus de fichiers et a un cold start plus lent. »

Résumé

Quand on compare des versions différentes d’un programme sous Windows, ce qui fonctionne vraiment n’est pas une astuce spectaculaire. Ce qui compte, c’est une discipline peu glorieuse mais efficace pour la reproductibilité, comme suit :

  • Fixer et consigner le secteur/batterie, le mode d’alimentation et le plan d’alimentation
  • Séparer cold et warm
  • Alterner les exécutions A / B
  • Regarder la médiane et la distribution
  • Clean boot si nécessaire
  • Si la différence est faible, creuser jusqu’à la raison avec ETW / WPR

Et le plus important est d’écrire, avec les résultats, ce que l’on a fixé et ce que l’on n’a pas fixé. Un benchmark est à la fois une comparaison de vitesse et un enregistrement des conditions expérimentales.

Un rapport d’accélération sans conditions écrites est aussi divertissant qu’une prédiction qui tombe juste de temps en temps, mais il reste bien peu fiable en matière de reproductibilité. À l’inverse, si les conditions sont correctement notées, le résultat a une vraie valeur, même si la différence est faible.

Références

Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.

Ces pages replacent le sujet dans un contexte plus large de services et de décisions.

Cet article est directement lié aux services suivants.

Analyse des bugs et des causes

Lorsqu'un écart de vitesse apparaît entre deux versions, la démarche consistant à isoler si la cause vient des conditions d'alimentation, de la chaleur, du bruit en arrière-plan ou de différences d'implémentation se prête bien à une mission d'investigation de bug et d'analyse de cause racine.

Questions fréquentes

Questions souvent posées lors d’une consultation sur le sujet de cet article.

Quelles sont les principales causes de variation des résultats de benchmark sous Windows ?
Il existe de nombreux facteurs à plusieurs niveaux : le mode d'alimentation et le plan d'alimentation, le secteur ou la batterie, la chaleur et le comportement du turbo, les mises à jour en arrière-plan, les analyses Defender, l'indexation de recherche, la synchronisation cloud, les notifications, l'ordonnancement et l'affinité, ainsi que l'état du cache. Même sur la même machine Windows, il s'agit en pratique d'une expérience différente si ces conditions ne sont pas alignées. Les disciplines de base consistent à comparer sur secteur avec un mode d'alimentation fixé, à redémarrer et attendre quelques minutes avant de mesurer, à alterner les exécutions A/B plutôt que d'exécuter toute une version avant l'autre, et à consigner les conditions avec les résultats.
Quelle est la différence entre le mode d'alimentation (power mode) et le plan d'alimentation (power plan) de Windows, et est-ce important pour le benchmark ?
Ce sont deux choses distinctes qui se ressemblent. Le mode d'alimentation est le curseur de l'application Paramètres (Meilleure efficacité énergétique / Équilibré / Meilleures performances), qui influence aussi le comportement de la gestion de l'alimentation du processeur, comme le Core Parking et la mise à l'échelle des performances. Le plan d'alimentation est le schéma d'alimentation traditionnel visible via powercfg, comme Équilibré ou Performances élevées. Traitez-les à la légère et votre comparaison devient une comparaison des politiques d'économie d'énergie de l'OS ; consignez donc au minimum : secteur ou batterie, quel mode d'alimentation, et quel plan d'alimentation actif. Notez que sur les appareils compatibles Modern Standby, seuls les plans dérivés d'Équilibré sont autorisés, donc l'absence de l'option Performances élevées relève de la conception.
Quels indicateurs de temps faut-il mesurer pour comparer des versions de programme ?
Regardez trois indicateurs : le temps wall-clock (via QueryPerformanceCounter ou Stopwatch) pour ce que l'utilisateur attend réellement ; le temps CPU (utilisateur plus noyau, via GetProcessTimes) pour l'efficacité de calcul ; et le nombre de cycles CPU (via QueryProcessCycleTime) pour savoir si le calcul lui-même est devenu plus léger. Ce sont les combinaisons qui racontent l'histoire : si le wall-clock s'est amélioré mais que le temps CPU n'a pas changé, le gain vient probablement des E/S, des attentes, du cache ou de l'ordonnancement plutôt que de l'implémentation. Préférez aussi la médiane, le p95 et la distribution à la moyenne, qu'une seule analyse Defender ou une notification peut entraîner ailleurs.
Faut-il exécuter mon benchmark avec une priorité élevée ou une affinité CPU fixée ?
Pas au départ. Mesurez d'abord dans l'état par défaut, car un écart qui apparaît là a de la valeur, et commencer avec /high ou /affinity importe des conditions qui ne se produisent pas sur un Windows réel. Utilisez-les uniquement avec un objectif clair : /high pour réduire les perturbations causées par d'autres processus, /affinity pour fixer le placement des CPU dans la comparaison, le contrôle NUMA pour aligner la localité mémoire sur les grosses machines. Évitez complètement /realtime : il tend à générer de nouveaux accidents plutôt qu'à supprimer du bruit. Quand une différence faible a besoin d'être expliquée, capturez plutôt une trace ETW avec Windows Performance Recorder.

Profil de l’auteur

Page de présentation de l’auteur de l’article.

Go Komura

Représentant de KomuraSoft LLC

Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.

Retour au blog