La performance d’une application Windows ne se joue pas uniquement dans le code. Le même .exe peut donner une impression différente selon le PC sur lequel il tourne.
Sur un PC, le traitement périodique est stable.
Sur un autre, il traîne parfois.
Sur secteur, tout va bien, mais sur batterie, c’est étrangement lent.
Vous avez monté la priorité dans le Gestionnaire des tâches, mais ce n’est pas devenu aussi rapide qu’espéré.
Vous pensiez avoir orienté le traitement vers les cœurs P, mais le temps de traitement continue de fluctuer.
À l’inverse, en cherchant à augmenter la performance, le ventilateur tourne sans arrêt et les autres applications deviennent lourdes.
En développant des applications Windows, on rencontre ce genre de « phénomènes difficiles à expliquer par le seul code ».
Dans ces cas-là, voici les quatre éléments à observer.
| Ce qu’on regarde | En résumé |
|---|---|
| Priorité | Quel thread s’exécute en premier |
| Affinité | Sur quel(s) CPU il est autorisé à s’exécuter |
| Cœurs P / Cœurs E | Si ce CPU penche vers la performance ou vers l’économie d’énergie |
| Réglages d’économie d’énergie | À quel point le CPU est autorisé à tourner à plein régime |
Sur les versions récentes de Windows, s’y ajoutent aussi EcoQoS et le Efficiency mode (mode Efficacité) du Gestionnaire des tâches.
Autrement dit, l’environnement d’exécution d’une application Windows ne se résume pas à « le CPU est-il rapide ou lent ».
Quand est-il exécuté
Où est-il exécuté
Sur quel type de cœur est-il exécuté
Dans quel état de performance le CPU fonctionne-t-il
L'OS le considère-t-il comme « prioritaire en performance » ou « pouvant tourner en économie d'énergie »
C’est la combinaison de ces éléments qui détermine la réactivité et le temps de traitement réels.
Cet article fait le point sur les relations entre priorité, affinité, cœurs P/E et réglages d’économie d’énergie — des aspects faciles à négliger dans le développement d’applications Windows.
Le code présenté dans cet article est publié sur GitHub sous forme d’un ensemble d’échantillons compilables et exécutables (une bibliothèque et une démo C# gérant priorité et affinité, des scripts PowerShell, et des tests unitaires).
windows-app-cpu-priority-affinity-power - komurasoft-blog-samples (GitHub)
1. D’abord la vue d’ensemble
Pour commencer, voici la vue d’ensemble sous forme de schéma.
flowchart LR A["Code de l'application"] --> B["Planificateur Windows"] P["Priorité<br/>à quel point il est exécuté rapidement"] --> B AF["Affinité / CPU Sets<br/>sur quel(s) CPU il peut s'exécuter"] --> B Q["QoS / EcoQoS<br/>orienté performance ou économie d'énergie"] --> B B --> C["Choix du thread à exécuter"] C --> D["Choix du processeur logique d'exécution"] PE["Cœurs P / Cœurs E<br/>orientés performance ou efficacité"] --> D PM["Mode d'alimentation / plan d'alimentation / PPM<br/>fréquence, boost, Core Parking"] --> D D --> R["Réactivité réelle<br/>temps de traitement<br/>échauffement<br/>consommation de batterie<br/>impact sur les autres applications"]
Ce qui compte, c’est que ces éléments ne sont pas indépendants.
Augmentez la priorité, et le thread aura plus de chances de s’exécuter.
Mais si le CPU lui-même est piloté vers l’économie d’énergie, il ne deviendra peut-être pas aussi rapide qu’espéré.
Restreignez les CPU avec l’affinité, et les migrations de thread diminueront peut-être.
Mais si le périmètre restreint tombe sur des cœurs orientés efficacité, ou s’il ne s’accorde pas avec le Core Parking et la gestion de l’alimentation, cela peut se retourner contre vous.
Orientez le traitement vers les cœurs P, et les calculs deviendront peut-être plus rapides.
Mais en poussant tout vers le côté haute performance, l’échauffement, le bruit du ventilateur, la consommation de batterie et l’impact sur les autres processus augmentent.
Le réglage de performance d’une application Windows n’est pas une simple chasse au « bouton qui accélère tout ».
Quel traitement voulez-vous rendre rapide ?
Quel traitement peut rester lent ?
Priorisez-vous la réactivité aux actions de l’utilisateur ?
Priorisez-vous le temps d’achèvement des traitements en arrière-plan ?
Jusqu’où tolérez-vous la consommation de batterie et l’échauffement ?
C’est une question de conception.
2. La priorité, c’est « à quel point il est exécuté rapidement »
Sous Windows, lorsque plusieurs threads sont exécutables, le planificateur décide « quel thread placer ensuite sur le CPU ». C’est là qu’intervient la priorité.
La priorité se détermine, grosso modo, en deux étapes.
Classe de priorité du processus
+ priorité relative du thread
= priorité de base du thread
Dans l’API Win32, il y a SetPriorityClass côté processus et SetThreadPriority côté thread.
Pour voir en PowerShell la priorité d’un processus en cours d’exécution, par exemple :
Get-Process -Id $PID | Select-Object Id, ProcessName, PriorityClass
Pour augmenter la priorité du processus PowerShell courant :
$p = Get-Process -Id $PID
$p.PriorityClass = "AboveNormal"
En C#, cela peut s’écrire ainsi :
using System.Diagnostics;
using var process = Process.GetCurrentProcess();
process.PriorityClass = ProcessPriorityClass.AboveNormal;
Il faut ici garder à l’esprit que la priorité n’est pas un réglage qui « accélère le CPU ». Ce que la priorité affecte, c’est quel thread s’exécute en premier en cas de conflit.
Ce n’est pas un réglage qui augmente la fréquence du CPU.
Ce n’est pas non plus un réglage qui sélectionne les cœurs P.
Ce n’est pas un réglage qui accélère les E/S.
Ce n’est pas non plus un réglage qui supprime les attentes de verrou ou les attentes réseau.
C’est pourquoi il est tout à fait courant de constater « j’ai augmenté la priorité, mais ça n’est pas devenu plus rapide ». Par exemple, si la lenteur provient de l’un des éléments suivants, augmenter la priorité ne résout pas le problème de fond :
- Attente d’E/S disque
- Attente réseau
- Attente de réponse d’une base de données
- Conflit de verrous
- Pause du GC
- Blocage du thread d’interface utilisateur
- Attente côté GPU ou pilote
- Analyse de fichiers par un antivirus
- Fréquence du CPU bridée vers l’économie d’énergie
Par ailleurs, HIGH_PRIORITY_CLASS et REALTIME_PRIORITY_CLASS ne sont pas à utiliser à la légère.
Un thread qui continue de s’exécuter longtemps à haute priorité cède difficilement du temps CPU aux autres threads.
Si cela restait cantonné à votre propre application, passe encore — mais cela peut dégrader la réactivité de l’ensemble du système.
La priorité, c’est un peu comme un médicament.
Dans les situations où elle agit, elle agit.
Mais ce n’est pas en augmentant la dose que ça marche mieux.
Ce qu’il faut examiner avant d’augmenter la priorité
Avant d’augmenter la priorité, il y a des points à considérer en premier lieu.
| Question | Ce qu’il faut regarder |
|---|---|
| Ce traitement est-il vraiment limité par le CPU ? | Utilisation du CPU, ETW, profileur |
| Bloque-t-on le thread d’interface utilisateur ? | Réactivité de l’UI, passage à l’asynchrone, conception de la file d’attente |
| La fenêtre à haute priorité est-elle courte ? | Élever temporairement, puis restaurer une fois terminé |
| Cela dérange-t-il d’autres applications ? | Impact sur la saisie, l’impression, les navigateurs, les logiciels résidents |
| Les droits ou la politique chez le client bloquent-ils cela ? | Droits administrateur, utilisateur d’exécution, produits de sécurité |
Ce qui compte dans une application Windows, ce n’est pas de toujours tourner à la priorité maximale, mais de prioriser le traitement nécessaire, au moment nécessaire, et uniquement sur le périmètre nécessaire.
3. L’affinité, c’est « sur quel(s) CPU il peut s’exécuter »
Si la priorité, c’est « à quel point il est exécuté rapidement », l’affinité, c’est « sur quel(s) CPU il peut s’exécuter ».
Sous Windows, on peut spécifier, pour un processus ou un thread, l’ensemble des processeurs logiques sur lesquels il est autorisé à s’exécuter.
Dans l’API Win32, il y a SetProcessAffinityMask pour les processus et SetThreadAffinityMask pour les threads.
Pour voir en PowerShell l’affinité d’un processus, par exemple :
Get-Process -Id $PID | Select-Object Id, ProcessName, ProcessorAffinity
À des fins de vérification, pour restreindre le processus PowerShell courant aux 4 premiers processeurs logiques, on peut écrire :
$p = Get-Process -Id $PID
$p.ProcessorAffinity = [IntPtr]0xF
0xF vaut 1111 en binaire.
Autrement dit, cela signifie que les processeurs logiques 0 à 3 sont autorisés.
Mais ceci n’est qu’un exemple destiné à la vérification.
Restreindre l’affinité peut améliorer la localité du cache CPU ou réduire les fluctuations dans un traitement périodique.
En revanche, cela revient aussi à enfermer les threads dans un espace étroit, alors que Windows aurait pu les faire migrer vers des CPU libres.
Il faut être particulièrement prudent dans des environnements comme ceux-ci :
- Cœurs P et cœurs E coexistent
- Avec SMT/Hyper-Threading, la correspondance entre processeurs logiques et cœurs physiques n’est pas intuitive
- Configuration NUMA
- Au-delà de 64 processeurs logiques, les Processor Groups entrent en jeu
- Le Core Parking est activé
- La gestion de l’alimentation par l’OEM ou le BIOS est agressive
- Exécution dans un environnement virtualisé
L’affinité est un réglage qui impose au système une contrainte assez forte : « ne t’exécute que sur ces CPU-là ».
Les contraintes peuvent être un outil de stabilisation.
Mais si on se trompe, on ferme les échappatoires.
Il existe aujourd’hui aussi les CPU Sets
Le masque d’affinité classique est une contrainte assez forte.
Windows dispose par ailleurs d’un mécanisme appelé CPU Sets.
Les CPU Sets constituent une API permettant à l’application de communiquer ses préférences de CPU de manière plus souple.
Dans la description de Microsoft, les CPU Sets sont présentés comme une spécification d’affinité « douce » (« soft »), compatible avec la gestion de l’alimentation de l’OS.
Voulez-vous fixer strictement les CPU ?
Ou voulez-vous orienter approximativement l’emplacement d’exécution, tout en coopérant avec la gestion de l’alimentation et la planification de l’OS ?
Cette distinction est importante.
Plutôt que de tout vouloir résoudre avec l’ancien SetProcessAffinityMask, une application Windows moderne doit aussi prendre en compte les CPU Sets et le QoS.
4. Cœurs P/Cœurs E : « le CPU a lui aussi une personnalité »
Sur les CPU récents, tous les cœurs n’ont pas nécessairement la même performance ni la même consommation électrique. L’exemple représentatif, ce sont les cœurs P et les cœurs E : en résumé, les cœurs P penchent vers la performance, les cœurs E vers l’efficacité.
| Type | Points forts |
|---|---|
| Cœurs P | Faible latence, haute performance mono-thread, traitement lourd au premier plan |
| Cœurs E | Économie d’énergie, traitement en arrière-plan, absorption du traitement parallèle |
Cependant, il est risqué pour un développeur de figer à la légère une hypothèse du type « les CPU 0 à 7 sont des cœurs P, les 8 à 15 des cœurs E ». L’ordre de numérotation des CPU peut varier selon le CPU, le BIOS, la version de Windows, le firmware, les réglages OEM et l’environnement de virtualisation.
Côté Windows, les informations des CPU Sets comportent une notion appelée EfficiencyClass.
Sur un système à processeurs hétérogènes, cette valeur indique les caractéristiques d’efficacité de ce CPU Set. La documentation de Microsoft explique qu’un CPU Set avec une valeur plus élevée dispose d’un processeur plus rapide mais moins efficace en énergie.
Pour travailler correctement avec les cœurs P/E, il ne suffit pas de regarder les numéros de CPU. Pour vraiment aller au fond des choses, il faut des observations comme celles-ci :
- Regarder
EfficiencyClassvia l’API CPU Sets - Observer le CPU d’exécution de chaque thread avec Windows Performance Recorder / Analyzer
- Observer les tendances dans l’affichage des processeurs logiques du Gestionnaire des tâches
- Mesurer les temps de traitement sur chaque machine physique
- Comparer secteur et batterie
- Comparer entre différents modes d’alimentation
Les cœurs P/E ne sont pas une simple spécification matérielle : combinés au planificateur Windows, au QoS et aux réglages d’économie d’énergie, ils déterminent où l’exécution atterrit réellement.
5. Les réglages d’économie d’énergie déterminent « à quel point le CPU tourne réellement à plein régime »
C’est un point qui compte énormément sur le terrain.
La priorité, c’est « quel thread s’exécute en premier ».
L’affinité, c’est « sur quel(s) CPU il peut s’exécuter ».
Les cœurs P/E, c’est « si ce CPU penche vers la performance ou vers l’efficacité ».
Et les réglages d’économie d’énergie concernent
la fréquence et l'état de puissance dans lesquels le CPU fonctionne, tout simplement
Autrement dit, voici ce qui peut se produire :
Vous avez augmenté la priorité.
Vous avez orienté le traitement vers les cœurs P.
Mais si les réglages d'alimentation penchent vers l'économie d'énergie,
le CPU ne tournera peut-être pas à plein régime.
C’est une histoire très caractéristique de Windows.
Sous Windows 11, on peut choisir le mode d’alimentation depuis l’application Paramètres, sous « Système > Alimentation et batterie ».
Les libellés varient selon l’environnement et la version, mais les orientations sont globalement les suivantes.
| Mode d’alimentation | Orientation |
|---|---|
| Meilleure efficacité énergétique / Best power efficiency | Priorise la batterie et l’économie d’énergie |
| Équilibré / Balanced | Équilibre entre performance et énergie |
| Performances optimales / Best performance | Priorise la performance |
De plus, les plans d’alimentation traditionnels comprennent Économies d'énergie (Power Saver), Équilibré (Balanced) et Performances élevées (High Performance).
Équilibré ajuste la performance et la consommation en fonction de la demande, tandis que Performances élevées est un réglage qui vise le maximum de performance au prix de la consommation.
Même si les réglages visibles par l’utilisateur sont simples, ils reposent, en coulisses, sur les réglages de Processor Power Management (PPM).
6. P-state, C-state, boost et EPP
Un CPU ne tourne pas en permanence à sa fréquence maximale ; il dispose d’états destinés à réduire la consommation.
| Terme | En résumé |
|---|---|
| P-state | État de performance qui fait varier la fréquence et la tension du CPU |
| C-state | État d’économie d’énergie qui arrête certaines fonctions du CPU au repos |
| Boost | Mécanisme qui entre dans un état de performance supérieur aux specs nominales lorsque les conditions le permettent |
| EPP | Energy Performance Preference. La préférence entre priorité à la performance et priorité à l’économie d’énergie |
Le P-state est le mécanisme qui réduit la consommation en faisant varier la fréquence et la tension du CPU.
Le C-state est le mécanisme par lequel le CPU arrête certaines fonctions au repos pour entrer dans un état d’économie d’énergie plus profond.
La gestion de l’alimentation de Windows utilise ces mécanismes pour équilibrer performance et consommation.
C’est pourquoi le phénomène « haute priorité mais quand même lent » est tout à fait possible.
Le thread est exécuté en priorité.
Mais la fréquence du CPU est basse.
Le boost peine à s’enclencher.
L’EPP penche vers l’économie d’énergie.
Le Core Parking limite les cœurs utilisables.
Sur batterie, l’ensemble de l’OS penche vers l’économie d’énergie.
Dans un tel cas, regarder uniquement la priorité ne permet pas de remonter à la cause.
En particulier pour le traitement périodique, le traitement d’image, le contrôle d’instruments, le traitement vidéo, le traitement audio, la capture par caméra USB et la communication série, le problème n’est pas seulement le temps de traitement moyen, mais le « retard occasionnel ».
La moyenne est rapide.
Mais une fois sur mille, ça traîne.
Cette seule fois sature le tampon.
L’interface se fige.
Le timing avec l’équipement se décale.
Pour ce genre de phénomène, la moyenne d’utilisation du CPU ne suffit pas.
Il faut regarder ensemble la distribution des temps de traitement, le maximum, les valeurs aberrantes, l’état d’alimentation, le CPU d’exécution et la charge en arrière-plan.
7. Le Core Parking concerne « le nombre de cœurs utilisables »
Windows dispose d’un mécanisme appelé Core Parking. C’est un contrôle qui met au repos les processeurs logiques non utilisés.
Lorsque l’utilisation est faible, il fait basculer certains cœurs vers des états de faible consommation afin de réduire la consommation électrique.
Dans la documentation de Microsoft, CPMinCores est décrit comme le réglage qui spécifie le pourcentage minimal de processeurs logiques devant rester un-parked, c’est-à-dire disponibles, à un instant donné.
Fixer la valeur à 100 % désactive l’algorithme de Core Parking.
Ce qui pose problème ici, c’est la combinaison avec l’affinité.
Vous avez restreint les threads avec l’affinité : « exécute-toi sur ce groupe de CPU ».
Mais la façon dont la gestion de l’alimentation traite ces cœurs en particulier est une question distincte.
La documentation Microsoft destinée à Windows Server explique de même que, lorsque des threads actifs sont fortement affinitisés à un sous-ensemble de CPU au sein d’un nœud NUMA, il existe des situations où cela ne s’accorde pas avec les décisions du Core Parking.
Cette façon de penser reste instructive pour les PC clients aussi.
L’affinité impose une contrainte au planificateur.
Le Core Parking concerne les cœurs que la gestion de l’alimentation maintient dans un état utilisable.
Considérer ces deux éléments séparément conduit à se tromper sur la cause.
8. EcoQoS / Efficiency Mode : signaler « ce traitement peut tourner en économie d’énergie »
Autrefois, le réglage de performance d’une application Windows tournait surtout autour de l’augmentation ou de la baisse de la priorité, et du changement d’affinité. Le Windows moderne propose cependant une autre notion. C’est le QoS.
Le QoS, Quality of Service, est une notion qui indique, par thread, « à quel point ce traitement doit privilégier la performance, ou à quel point il peut privilégier l’économie d’énergie ».
La documentation de Microsoft explique que si la priorité de planification reste le principal critère pour décider quel thread s’exécute ensuite, le QoS peut, lui, influencer la sélection des cœurs et la gestion de l’alimentation du processeur.
En particulier, EcoQoS est le mécanisme qui permet de traiter, du côté économie d’énergie, les traitements pour lesquels la performance n’est pas l’élément le plus important.
En C++, on peut par exemple placer le thread courant en EcoQoS en utilisant SetThreadInformation avec ThreadPowerThrottling.
#include <windows.h>
void EnableEcoQoSForCurrentThread()
{
THREAD_POWER_THROTTLING_STATE powerThrottling = {};
powerThrottling.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
powerThrottling.ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
powerThrottling.StateMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
SetThreadInformation(
GetCurrentThread(),
ThreadPowerThrottling,
&powerThrottling,
sizeof(powerThrottling));
}
À l’inverse, pour revenir à un comportement orienté performance, on remet StateMask à 0 pour la même cible de contrôle.
void DisableEcoQoSForCurrentThread()
{
THREAD_POWER_THROTTLING_STATE powerThrottling = {};
powerThrottling.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
powerThrottling.ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
powerThrottling.StateMask = 0;
SetThreadInformation(
GetCurrentThread(),
ThreadPowerThrottling,
&powerThrottling,
sizeof(powerThrottling));
}
EcoQoS n’est pas une fonctionnalité où « tout mettre en économie d’énergie » serait la bonne réponse. Voici, par exemple, les traitements qui s’y prêtent :
- Synchronisation en arrière-plan
- Construction d’index à basse priorité
- Agrégation de journaux non urgente
- Mise à jour de cache non directement liée à une action de l’utilisateur
- Traitement de maintenance qui n’a besoin de se terminer qu’à terme
En revanche, il faut rester prudent pour des traitements comme ceux-ci :
- Traitement directement lié à une action de l’interface utilisateur
- Capture caméra
- Traitement audio
- Traitement lié à un cycle de contrôle
- Traitement de décision d’un équipement d’inspection
- Export que l’utilisateur attend
- Traitement nécessitant une réponse proche du temps réel
Le Efficiency mode (mode Efficacité) du Gestionnaire des tâches est lié à cette même idée.
Le blog Performance Diagnostics de Microsoft explique qu’activer l’Efficiency mode abaisse la priorité de base du processus à Low et fixe son QoS à EcoQoS.
Autrement dit, l’Efficiency mode n’est pas une simple « icône d’économie d’énergie » : c’est un mécanisme qui combine l’abaissement de priorité et l’EcoQoS pour protéger la réactivité et l’efficacité énergétique de l’application au premier plan.
Du point de vue du développeur, c’est assez important.
Cela permet une conception où l’on peut dire à l’OS non seulement « je veux que ce traitement se termine vite », mais aussi
« ce traitement doit simplement s’exécuter sans gêner l’utilisateur ».
9. Un arbre de décision
Ce qui précède étant complexe, voici un arbre de décision pour investiguer la performance et les fluctuations de cycle d’une application Windows.
flowchart TD
A["Symptômes<br/>lent, cycles qui fluctuent, UI figée, ventilateur bruyant"] --> B["D'abord, enregistrer<br/>temps de traitement / maximum / utilisation CPU / état d'alimentation / secteur ou batterie / PC concerné"]
B --> C{"Le CPU est-il la cause principale ?"}
C -- "Non / inconnu" --> D["Vérifier E/S, verrous, BD, réseau, GC, GPU, pilotes<br/>éliminer les attentes avant de toucher à la priorité ou à l'affinité"]
C -- "Oui" --> E{"Y a-t-il une forte contention CPU avec d'autres processus ?"}
E -- "Oui" --> F["Envisager la priorité<br/>mais en limiter le périmètre<br/>éviter l'usage courant de High/Realtime"]
E -- "Non" --> G{"L'exécution est-elle déséquilibrée vers certains CPU ?"}
G -- "Oui" --> H["Vérifier l'affinité / les CPU Sets<br/>ne fixe-t-on pas trop fort<br/>tient-on compte des cœurs P/E et de NUMA"]
G -- "Non" --> I{"La fréquence ou l'état d'alimentation sont-ils suspects ?"}
I -- "Oui" --> J["Vérifier le mode d'alimentation / le plan d'alimentation / le PPM<br/>suspecter le P-state / l'EPP / le boost / le Core Parking"]
I -- "Non" --> K{"Un traitement en arrière-plan gêne-t-il le premier plan ?"}
K -- "Oui" --> L["Envisager EcoQoS / Efficiency Mode / l'abaissement de priorité<br/>faire basculer le traitement non urgent vers le côté économie d'énergie"]
K -- "Non" --> M["Revoir l'algorithme, le degré de parallélisme, la conception des files d'attente et du thread d'interface utilisateur"]
F --> N["Changer un élément à la fois et mesurer en A/B"]
H --> N
J --> N
L --> N
M --> N
N --> O["Regarder non seulement la moyenne, mais<br/>le maximum, les valeurs aberrantes, l'échauffement et l'impact sur les autres applications"]
Ce qui compte dans cet arbre, c’est de ne pas toucher aux réglages dès le départ. On enregistre d’abord.
- La lenteur est-elle constante ?
- Ou seulement occasionnelle ?
- Secteur ou batterie ?
- Quel est le mode d’alimentation ?
- Le mode Efficacité est-il actif dans le Gestionnaire des tâches ?
- L’utilisation du CPU est-elle élevée ?
- La fréquence monte-t-elle ?
- Quel thread utilise le CPU ?
- Quelle est l’ampleur du temps de traitement maximal ?
- Un autre logiciel résident ou un antivirus est-il impliqué ?
Ensuite, on change les choses une par une.
Changer la priorité.
Changer l’affinité.
Changer le mode d’alimentation.
Appliquer EcoQoS.
Séparer le traitement en arrière-plan.
Insérer une file d’attente.
Sortir le traitement du thread d’interface utilisateur.
Changer plusieurs éléments à la fois, et on ne sait plus ce qui a fait effet.
10. Commandes de vérification sur le terrain
Lorsqu’une application Windows se comporte différemment selon l’environnement, il est utile de pouvoir d’abord capturer l’état du système.
Voir les informations du CPU
Get-CimInstance Win32_Processor |
Select-Object Name, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed
Voir le plan d’alimentation actif
powercfg /getactivescheme
Voir les réglages de gestion de l’alimentation du processeur
powercfg /q SCHEME_CURRENT SUB_PROCESSOR
La sortie est assez longue, mais on peut y vérifier les réglages liés à l’état minimal/maximal du processeur, à l’EPP, au boost et au Core Parking.
Les éléments visibles varient selon l’environnement.
Générer un rapport de diagnostic d’efficacité énergétique
À exécuter dans un terminal avec des droits administrateur.
powercfg /energy
Après une mesure d’une durée fixe, un rapport HTML est produit.
C’est un point d’entrée pour examiner les pilotes, les périphériques, la résolution du minuteur, l’économie d’énergie de l’USB, les blocages de mise en veille, etc.
Voir la priorité et l’affinité d’un processus cible
Get-Process -Name MyApp |
Select-Object Id, ProcessName, PriorityClass, ProcessorAffinity
Voir l’état de performance du CPU
Les noms de compteurs disponibles varient selon l’environnement, mais ces compteurs de performance sont une référence utile.
Get-Counter '\Processor Information(_Total)\% Processor Performance'
Get-Counter '\Processor Information(_Total)\% Processor Utility'
Pour une investigation sérieuse, capturer de l’ETW avec Windows Performance Recorder et Windows Performance Analyzer est plus fiable.
On peut y suivre ensemble les fluctuations de cycle, les changements de contexte, le CPU d’exécution, les DPC/ISR, les E/S disque et les variations de fréquence du CPU.
11. Pour un traitement quasi temps réel, il faut tout considérer ensemble
Windows n’est pas un OS temps réel au sens habituel du terme. Pourtant, les applications Windows du terrain se voient parfois demander des caractéristiques proches du temps réel.
- Capturer des images depuis une caméra USB à un cycle fixe
- Échanger avec un équipement via une communication série
- Lire des données depuis des instruments de mesure
- Se synchroniser avec des automates (PLC) et des équipements externes
- Traiter de l’audio ou de la vidéo
- Renvoyer des résultats d’inspection dans un délai fixe
- Faire tourner un calcul lourd sans figer l’interface utilisateur
Pour ce genre de traitement, un code rapide ne suffit pas.
Il faut une conception des threads.
Il faut une conception des files d’attente.
Il faut de la journalisation.
Il faut des délais d’expiration.
Il faut de la contre-pression (backpressure).
Il faut décider, en cas de retard, s’il faut abandonner, attendre ou réessayer.
Et par-dessus tout cela, il faut examiner la priorité, l’affinité, les cœurs P/E et les réglages d’économie d’énergie.
Prenons par exemple un thread de capture caméra.
Ce thread est proche de l’action de l’utilisateur et présente une périodicité.
Il ne devrait peut-être pas être en EcoQoS.
Augmenter légèrement sa priorité vaut peut-être le coup.
Mais l’augmenter trop nuit à l’interface utilisateur et aux autres traitements.
Fixer son affinité pourrait le stabiliser.
Mais si la cible fixée penche vers les cœurs E, cela pourrait avoir l’effet inverse.
Si le mode d’alimentation penche vers l’économie d’énergie, cela pourrait ne traîner que sur batterie.
Qu’en est-il, en revanche, de la compression d’anciens journaux ?
C’est peut-être un traitement que l’utilisateur n’attend pas.
Dans ce cas, on abaisse sa priorité.
On le met en EcoQoS.
On le fait tourner à l’inactivité.
On ne le fait tourner que sur secteur.
Une conception de ce type est plus prévenante pour l’application dans son ensemble.
Plutôt que de rendre tous les traitements « rapides », on sépare le traitement qui doit être rapide de celui qui ne doit pas gêner.
12. Principes de conception de base
Pour aborder ces sujets dans une application Windows, il existe six principes de base.
1. Ne pas figer les réglages dès le départ
Il vaut mieux ne pas fixer fortement la priorité ou l’affinité dès le départ.
Le planificateur Windows fait, dans la plupart des cas, un travail plutôt bon.
Imposer des contraintes superflues du côté de l’application peut au contraire aggraver la situation.
D’abord, construire normalement.
Mesurer.
Quand un problème apparaît, formuler une hypothèse.
Faire un petit changement.
Mesurer à nouveau.
C’est cet ordre-là.
2. Utiliser la priorité de manière temporaire
Réservez la haute priorité aux seuls intervalles qui en ont besoin.
Plutôt que de rester en permanence à haute priorité,
l'élever juste avant le traitement important
la restaurer une fois terminé
est plus sûr.
3. Envisager l’affinité en dernier
L’affinité est un réglage fort.
Elle peut être efficace lorsqu’on soupçonne des fluctuations de cycle ou des effets de migration entre CPU.
Mais ce n’est pas le premier réglage à toucher.
En particulier, si vos clients disposent de plusieurs types de PC, figer les numéros de CPU est risqué.
4. Ne pas figer les cœurs P/E, les observer
Si vous voulez utiliser les cœurs P et E de manière différenciée, observez d’abord sur des machines réelles.
Plutôt que de figer un choix par numéro de CPU, regardez les CPU Sets, l’EfficiencyClass, l’ETW et les mesures réelles.
5. Tester en prenant les réglages d’économie d’énergie comme hypothèse de base
« C’est rapide parce que la machine de développement est sur secteur avec des réglages haute performance » ne suffit pas.
Dans les environnements clients, des états comme ceux-ci sont tout à fait normaux :
- Un portable fonctionnant sur batterie
- Meilleure efficacité énergétique
- Économiseur d’énergie
- Utilitaires d’économie d’énergie propres à l’OEM
- Réglages d’alimentation figés par une politique d’entreprise
- PC fins dont la performance chute sous l’effet de la chaleur
- Postes de travail chargés de nombreux logiciels résidents
Pour les tests de performance, il est souhaitable d’examiner séparément au moins ces conditions.
| Condition | Ce qu’il faut regarder |
|---|---|
| Secteur + Performances optimales | Un état proche de la performance maximale |
| Secteur + Équilibré | Un usage professionnel standard |
| Batterie + Équilibré | La réalité des PC portables |
| Batterie + Meilleure efficacité énergétique | La limite basse côté économie d’énergie |
| Exécution continue longue | Échauffement, ventilateurs, thermal throttling |
| Utilisation simultanée d’autres applications | Cohabitation avec navigateurs, Teams, Excel, antivirus |
6. Envisager EcoQoS pour les traitements en arrière-plan
Pour les traitements qui ne sont pas directement liés à l’expérience utilisateur, il est souvent préférable de privilégier la discrétion plutôt que de chercher la performance.
Une application qui fait tout tourner à haute performance est peut-être rapide.
Mais elle gêne les autres travaux.
Elle fait tourner les ventilateurs du portable.
Elle consomme la batterie.
Le résultat est une application désagréable à utiliser.
Pour une application Windows, « bien cohabiter » fait aussi partie de la qualité, pas seulement la vitesse.
13. Idées reçues fréquentes
Augmenter la priorité rend forcément plus rapide
Pas nécessairement.
Si la contention CPU est la cause, cela peut fonctionner.
Mais si la cause est une attente d’E/S, une attente de verrou, une basse fréquence due à l’économie d’énergie, ou une exécution du côté des cœurs E, la priorité seule ne suffit pas.
Figer sur les cœurs P est toujours la bonne réponse
Pas toujours.
Les cœurs P offrent une haute performance, mais l’échauffement et la consommation augmentent aussi.
Ils peuvent aussi entrer en concurrence avec d’autres traitements importants au premier plan.
Ce qui compte davantage, c’est de séparer le traitement qui doit aller vers les cœurs P de celui pour lequel les cœurs E suffisent.
Les réglages d’économie d’énergie relèvent de la préférence de l’utilisateur et ne concernent pas l’application
Ils la concernent bel et bien.
La même application s’exécute différemment selon le mode d’alimentation, le plan d’alimentation, l’EPP, le boost et le Core Parking.
Sur les PC portables en particulier, le comportement change entre le secteur et la batterie.
L’Efficiency mode ne fait que ralentir
Ce n’est pas que ralentir.
Par l’abaissement de priorité et l’EcoQoS, c’est un mécanisme qui protège la réactivité et l’efficacité énergétique de l’application au premier plan.
Pour les traitements en arrière-plan non urgents, cela vaut même la peine d’y penser de manière proactive.
C’est parce que c’est Windows que c’est instable
C’est aussi une vision un peu grossière.
Windows n’est pas un OS temps réel.
Mais en comprenant la planification, la gestion de l’alimentation, le QoS, la mesure, la journalisation et la conception des threads, on peut le stabiliser de façon tout à fait exploitable sur le terrain.
Le problème n’est pas « c’est impossible parce que c’est Windows », mais le fait de ne pas regarder ce qui se passe, et à quelle couche.
14. Concevoir la journalisation avant l’implémentation
Ce type de problème peut ne survenir que chez le client. Il est donc utile de rendre l’application capable de conserver au minimum des informations de diagnostic.
Par exemple, le journal de diagnostic peut contenir des informations comme celles-ci :
- Version de l’application
- Version de Windows
- Nom du CPU
- Nombre de processeurs logiques
- Secteur ou batterie
- Moyenne, maximum et percentiles du temps de traitement
- Nombre de retards du cycle de traitement
- Priorité du thread concerné
- Priorité du processus
- Présence ou non d’un réglage d’affinité
- Présence ou non d’un réglage EcoQoS
- Plan d’alimentation au démarrage
- Nombre de fois où le traitement concerné a expiré (timeout)
Quand un client dit « c’est parfois lent », sans aucune trace, on en est réduit à deviner. Avec des journaux, on peut formuler des hypothèses.
Lent uniquement sur batterie
Lent uniquement sur un PC précis
Lent uniquement juste après le démarrage
Lent à partir de 30 minutes
Lent uniquement lorsqu'une autre application tourne
Des valeurs aberrantes apparaissent à cycle fixe
Une fois ces différences visibles, il devient bien plus facile de déterminer s’il s’agit de la priorité, de l’affinité, des réglages d’alimentation, de la chaleur, ou d’une autre attente.
15. Le point de vue de Komura Soft
Dans le développement d’applications Windows, la théorie pure ne suffit pas.
Fonctionner sur le PC du client.
Fonctionner sur les terminaux du terrain.
Cohabiter avec d’anciens périphériques.
Fonctionner dans des environnements avec antivirus, imprimantes et politiques internes de l’entreprise.
Ne pas s’effondrer sous les réglages d’économie d’énergie d’un PC portable.
Là où la performance est nécessaire, la délivrer réellement.
Pour les traitements non urgents, ne pas gêner l’utilisateur.
Pour y parvenir, mieux vaut ne pas considérer Windows comme une simple « boîte noire d’OS ».
Windows réfléchit à la manière de faire tourner vos threads.
Il réfléchit à sur quel CPU les faire tourner.
Il équilibre puissance et performance.
Il gère des cœurs hétérogènes comme les cœurs P et E.
Il cherche à distinguer les applications au premier plan des traitements en arrière-plan.
Le développeur ne doit pas s’y opposer, mais communiquer son intention là où c’est nécessaire.
Ce traitement fait attendre l’utilisateur.
Ce traitement peut être un peu lent.
Ce traitement a un cycle critique.
Ce traitement doit juste tourner discrètement en arrière-plan.
Ce traitement ne doit gêner aucun autre traitement.
C’est cette conception qu’on traduit dans sa compréhension de la priorité, de l’affinité, du QoS et des réglages d’économie d’énergie.
16. Conclusion
La performance d’une application Windows ne se joue pas uniquement dans le code.
Augmentez la priorité, et le comportement peut rester en deçà des attentes si l’affinité a orienté le traitement vers les cœurs E.
Orientez-le vers les cœurs P, et le CPU peut ne pas délivrer sa performance maximale si le mode d’alimentation penche vers l’économie d’énergie.
Appliquez une affinité forte sans tenir compte des CPU Sets et du QoS, et vous risquez de fermer les échappatoires de la gestion de l’alimentation et du planificateur de Windows.
Poussez tout vers le côté haute performance, et l’échauffement, le bruit du ventilateur, la consommation de batterie et l’impact sur les autres applications augmentent tous.
Dans le développement d’applications Windows, il faut concevoir non seulement pour la vitesse, mais aussi pour la réactivité, la stabilité, la consommation, l’échauffement et la cohabitation avec les autres processus.
Et les éléments à observer restent ces quatre-là :
Priorité
Affinité
Cœurs P / Cœurs E
Réglages d'économie d'énergie
Et sur le Windows moderne, l’EcoQoS et l’Efficiency mode s’y ajoutent.
Il y a beaucoup de quoi s’inquiéter.
Mais il n’est pas nécessaire de laisser cette inquiétude à l’état d’anxiété.
Transformer l’inquiétude en mesure.
Transformer l’inquiétude en journaux.
Transformer l’inquiétude en conception.
Transformer l’inquiétude en conditions de test.
Faites cela, et Windows cesse d’être un environnement d’exécution capricieux pour devenir une plateforme qui mérite vraiment d’être observée sur le terrain.
Windows n’est pas un OS temps réel.
Malgré cela, en comprenant l’environnement d’exécution et en concevant en conséquence, on peut construire des applications sur lesquelles compter réellement sur le terrain.
Et c’est précisément cette difficulté qui fait aussi tout l’intérêt du développement d’applications Windows.
Liens de référence
- Le code source complet des échantillons de cet article (C# / PowerShell / tests unitaires) - komurasoft-blog-samples (GitHub)
- Scheduling Priorities - Microsoft Learn
- SetProcessAffinityMask function - Microsoft Learn
- SetThreadAffinityMask function - Microsoft Learn
- CPU Sets - Microsoft Learn
- SYSTEM_CPU_SET_INFORMATION structure - Microsoft Learn
- Change the power mode for your Windows PC - Microsoft Support
- Power Policy Settings - Microsoft Learn
- P-states and C-States - Microsoft Learn
- Processor power management options - Microsoft Learn
- CPMinCores - Microsoft Learn
- Quality of Service - Microsoft Learn
- SetThreadInformation function - Microsoft Learn
- Reduce Process Interference with Task Manager Efficiency Mode - Microsoft DevBlogs
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Externalisation et développement sur mesure d'une application Windows : ce qu'il faut clarifier avant de se lancer
Avant de confier l'externalisation ou le développement sur mesure d'une application Windows, voici les points à clarifier : révision d'un...
Gestion des erreurs et conception des nouvelles tentatives sous PowerShell — du piège du try/catch aux bonnes pratiques d'exit code et de retry
Cet article présente, du point de vue pratique, la différence entre erreurs terminales et non terminales sous PowerShell, le piège du try...
Politique d'exécution PowerShell et signature de scripts — Guide pratique pour sortir de l'exploitation « on colmate avec Bypass »
La politique d'exécution de PowerShell est « un dispositif de sécurité, pas une frontière de sécurité ». Cet article présente les différe...
Comment comprendre l'isolation des sessions Windows — Session 0, RDP et exécution simultanée de plusieurs utilisateurs
Cet article démêle le concept de « session » Windows, un sujet qui déroute régulièrement les développeurs d'applications Windows. Il expl...
Empêcher les lancements multiples d'une application Windows — Mutex nommé et activation de la fenêtre existante lors d'un second lancement
Cet article détaille comment implémenter la prévention des lancements multiples d'une application Windows métier à l'aide d'un Mutex nomm...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Comment configure-t-on la priorité CPU ?
- La priorité se détermine en deux étapes : la classe de priorité du processus et la priorité relative du thread. Dans l'API Win32, on trouve SetPriorityClass côté processus et SetThreadPriority côté thread. En PowerShell, on peut affecter une valeur comme "AboveNormal" à la propriété PriorityClass de l'objet obtenu via Get-Process, et en C#, on assigne ProcessPriorityClass.AboveNormal à la propriété PriorityClass de Process.GetCurrentProcess(). Cependant, l'usage permanent de HIGH_PRIORITY_CLASS ou REALTIME_PRIORITY_CLASS est à éviter, car cela dégrade la réactivité de l'ensemble du système.
- Pourquoi mon application ne devient-elle pas plus rapide après avoir augmenté sa priorité ?
- Parce que la priorité est un réglage qui détermine « quel thread s'exécute en premier en cas de conflit », et non un réglage qui accélère le CPU. Si la lenteur provient d'une attente d'E/S disque, d'une attente réseau, d'un conflit de verrous, d'une pause du GC, d'un blocage du thread d'interface utilisateur, d'une analyse par un antivirus, ou du fait que la fréquence du CPU est bridée par les réglages d'économie d'énergie, augmenter la priorité ne résout pas le problème de fond. Il est essentiel de d'abord enregistrer la distribution des temps de traitement, l'état d'alimentation et le CPU d'exécution pour isoler la cause.
- Que se passe-t-il lorsqu'on configure EcoQoS avec SetThreadInformation ?
- En indiquant ThreadPowerThrottling et THREAD_POWER_THROTTLING_EXECUTION_SPEED à SetThreadInformation, on signale à l'OS de traiter ce thread comme EcoQoS (un QoS orienté économie d'énergie). Le QoS pouvant influencer la sélection des cœurs et la gestion de l'alimentation du processeur, cela permet de faire basculer des traitements comme la synchronisation en arrière-plan ou l'agrégation de journaux non urgente vers le côté économe en énergie, sans gêner l'application au premier plan. En revanche, il faut rester prudent pour les traitements directement liés aux actions de l'utilisateur, à la capture caméra ou au cycle de contrôle. En remettant StateMask à 0, on revient à un comportement orienté performance.
- Qu'est-ce que CPMinCores dans powercfg ?
- CPMinCores est un réglage d'alimentation lié au Core Parking de Windows : il indique le pourcentage minimal de processeurs logiques devant rester un-parked (c'est-à-dire disponibles) à un instant donné. Une valeur de 100 % désactive l'algorithme de Core Parking. On peut vérifier le réglage actuel avec des droits administrateur en exécutant powercfg /q SCHEME_CURRENT SUB_PROCESSOR ; si l'affinité restreint déjà les CPU utilisables, il existe des situations où cela ne s'accorde pas avec les décisions du Core Parking, d'où la nécessité d'examiner les deux ensemble.
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.
Liens publics