Searching...
Français
EnglishEnglish
EspañolSpanish
简体中文Chinese
FrançaisFrench
DeutschGerman
日本語Japanese
PortuguêsPortuguese
ItalianoItalian
한국어Korean
РусскийRussian
NederlandsDutch
العربيةArabic
PolskiPolish
हिन्दीHindi
Tiếng ViệtVietnamese
SvenskaSwedish
ΕλληνικάGreek
TürkçeTurkish
ไทยThai
ČeštinaCzech
RomânăRomanian
MagyarHungarian
УкраїнськаUkrainian
Bahasa IndonesiaIndonesian
DanskDanish
SuomiFinnish
БългарскиBulgarian
עבריתHebrew
NorskNorwegian
HrvatskiCroatian
CatalàCatalan
SlovenčinaSlovak
LietuviųLithuanian
SlovenščinaSlovenian
СрпскиSerbian
EestiEstonian
LatviešuLatvian
فارسیPersian
മലയാളംMalayalam
தமிழ்Tamil
اردوUrdu
Writing High-Performance .NET Code

Writing High-Performance .NET Code

par Ben Watson 2014 280 pages
4.31
290 évaluations
Écouter
Try Full Access for 7 Days
Unlock listening & more!
Continue

Points clés

1. Mesurez tout : la performance repose sur les données.

Vous ne pouvez PAS identifier vos problèmes de performance sans mesures précises.

La performance ne s’improvise pas. Les intuitions et l’inspection du code peuvent orienter, mais seule une mesure rigoureuse révèle les véritables goulets d’étranglement. Optimiser prématurément du code non critique est une perte de temps ; concentrez vos efforts là où les données montrent un impact réel.

Définissez des objectifs quantifiables. Des notions vagues comme « rapide » ou « réactif » sont inutiles ; les exigences de performance doivent être claires et mesurables. Suivez des indicateurs tels que la latence (en utilisant des percentiles, pas seulement des moyennes), la consommation mémoire (ensemble de travail vs. mémoire privée) et le temps CPU sous des charges définies pour vérifier que vous atteignez vos objectifs.

Automatisez la mesure. Intégrez la surveillance des performances dans vos environnements de développement, de test et de production. Des outils comme les compteurs de performance et les événements ETW permettent un suivi continu et une analyse historique, fournissant des données solides pour justifier les améliorations et détecter rapidement les régressions.

2. Maîtrisez la mémoire : collaborez avec le ramasse-miettes.

Collectez les objets en génération 0 ou pas du tout.

Le ramasse-miettes est une fonctionnalité, pas un bug. Le garbage collector (GC) de .NET simplifie la gestion mémoire, mais nécessite une bonne compréhension pour optimiser la performance. Le principe fondamental est de rendre les objets soit très éphémères (nettoyés rapidement en Gen 0), soit très durables (promus en Gen 2 et conservés longtemps, souvent via des pools).

Réduisez le taux d’allocation et la durée de vie des objets. Le temps de collecte dépend des objets vivants, pas des objets alloués. Minimisez les allocations mémoire, surtout pour les gros objets (≥ 85 000 octets) qui vont dans le tas des gros objets (LOH), coûteux à collecter et sujets à la fragmentation. Mettez en place des pools pour les objets volumineux ou fréquemment utilisés afin d’éviter des allocations répétées.

Comprenez la configuration du GC. Choisissez le GC Workstation pour les applications desktop et le GC Server pour les serveurs dédiés afin de bénéficier de la collecte parallèle. Le GC en arrière-plan (par défaut) permet des collectes Gen 2 concurrentes. Utilisez les modes basse latence ou la compaction du LOH avec parcimonie et mesure attentive, car ils impliquent des compromis importants.

3. Optimisez le JIT : maîtrisez le démarrage et la génération de code.

La première exécution d’une méthode engendre toujours un coût de performance.

Le JIT ajoute un coût au démarrage. Le code .NET est compilé en langage intermédiaire (IL) puis compilé Just-In-Time (JIT) en code natif lors de la première exécution. Ce coût initial peut ralentir le démarrage de l’application ou la réactivité du premier appel d’une méthode.

Réduisez le temps de JIT. Limitez la quantité de code à compiler à la volée, surtout dans les chemins critiques de démarrage. Sachez que certaines fonctionnalités et API génèrent beaucoup d’IL caché, notamment :

  • le mot-clé dynamic
  • async et await (même si leurs bénéfices surpassent souvent le coût)
  • les expressions régulières (surtout non compilées ou complexes)
  • la génération de code (ex. sérialiseurs)

Exploitez la précompilation. Pour améliorer le démarrage, utilisez l’optimisation par profil (Multicore JIT) pour précompiler le code fréquemment utilisé. Pour les applications Universal Windows Platform, .NET Native compile en code natif à l’avance. Dans d’autres cas, NGEN (Native Image Generator) peut précompiler les assemblies, mais avec des compromis sur la localisation et la taille du code.

4. Adoptez l’asynchronie : évitez le blocage, maximisez le débit.

Pour obtenir la meilleure performance, votre programme ne doit jamais gaspiller une ressource en attendant une autre.

Le parallélisme est la clé du débit. Les applications modernes doivent exploiter plusieurs cœurs CPU. La programmation asynchrone est essentielle pour éviter que les threads se bloquent sur des opérations d’E/S (réseau, disque, base de données) ou autres ressources, permettant au système d’utiliser efficacement les cycles CPU en attendant.

Utilisez Tasks et async/await. La Task Parallel Library (TPL) et les mots-clés async/await sont la méthode recommandée pour gérer la concurrence en .NET. Ils abstraient la gestion du pool de threads et simplifient les workflows asynchrones complexes, rendant le code linéaire tout en évitant le blocage.

Ne bloquez jamais sur des E/S ou des Tasks. Évitez les appels d’E/S synchrones et ne faites jamais appel à .Wait() ou .Result sur une Task dans du code critique. Préférez await ou .ContinueWith() pour planifier le travail suivant, permettant au thread courant de retourner au pool et de gérer d’autres tâches.

5. Codez intelligemment : choisissez types et patterns avec soin.

L’optimisation poussée défie souvent les abstractions du code.

Comprenez le coût des types. Les classes (types référence) ont un surcoût par instance et vivent sur le tas, impactant le GC. Les structs (types valeur) n’ont pas ce surcoût et résident sur la pile ou en ligne dans d’autres objets, offrant une meilleure localité mémoire, surtout en tableaux. Privilégiez les structs pour les données petites et fréquemment utilisées afin de réduire la pression sur le GC et améliorer la cache.

Méfiez-vous des coûts cachés. Certaines fonctionnalités et API cachent des opérations coûteuses. Les propriétés sont des appels de méthode, pas un simple accès à un champ. Le foreach sur IEnumerable est souvent plus lent qu’un for sur un tableau à cause du coût de l’énumérateur. Le cast d’objets, surtout vers des interfaces ou dans la hiérarchie, a un coût.

Optimisez les opérations courantes. Pour les structs, implémentez toujours efficacement Equals, GetHashCode (IEquatable<T>) et CompareTo (IComparable<T>) pour éviter les défauts coûteux basés sur la réflexion et permettre des opérations optimisées sur les collections. Utilisez les retours et variables ref en C# 7+ pour éviter la copie de gros structs ou l’accès répété aux éléments de tableaux.

6. Connaissez votre framework : comprenez le coût des API.

Vous devez comprendre ce que fait le code derrière chaque API appelée.

Les API du framework ont des compromis. Le .NET Framework est généraliste ; ses API privilégient souvent la robustesse et la facilité d’usage au détriment de la performance brute. Ne supposez pas qu’un appel simple est forcément peu coûteux, surtout dans les chemins critiques.

Examinez et questionnez les API. Utilisez des décompilateurs (comme ILSpy) pour analyser l’implémentation des méthodes Framework que vous utilisez fréquemment. Recherchez les coûts cachés tels que :

  • allocations mémoire (notamment sur le LOH)
  • boucles ou algorithmes coûteux
  • recours à la réflexion ou au comportement dynamique
  • validations ou gestions d’erreur inutiles

Choisissez l’outil adapté. Pour les tâches courantes (collections, chaînes, E/S), .NET propose plusieurs API aux performances variables. Comparez-les (ex. différents parseurs XML, méthodes de concaténation de chaînes) pour trouver la meilleure option selon votre contexte.

7. Exploitez les outils : ETW, profileurs et débogueurs sont vos alliés.

PerfView, créé par l’architecte performance .NET de Microsoft (auteur de la préface de ce livre) Vance Morrison, est l’un des meilleurs par sa puissance.

Les outils sont indispensables au diagnostic. Une analyse performante repose sur des outils puissants pour collecter et interpréter les données. Ne vous fiez pas uniquement aux profileurs basiques intégrés aux IDE ; apprenez à utiliser des outils système avancés.

Outils clés et usages :

  • PerfView : collecte et analyse les événements ETW (CPU, GC, JIT, personnalisés). Idéal pour l’analyse des piles, la détection des points chauds d’allocation et la compréhension du comportement du GC.
  • WinDbg + SOS : débogueur puissant pour examiner l’état du tas managé, les racines d’objets, les objets épinglés et les piles de threads. Indispensable pour l’analyse approfondie des fuites mémoire.
  • Visual Studio Profiler : outils conviviaux pour analyser l’utilisation CPU et mémoire en développement.
  • Compteurs de performance : métriques système pour surveiller la santé globale et l’usage des ressources dans le temps.
  • Événements ETW : mécanisme de journalisation à faible overhead utilisé par l’OS et le CLR. Définissez des événements personnalisés pour corréler le comportement applicatif à la performance système.

Maîtrisez les données. Ces outils fournissent souvent des données brutes (événements ETW, dumps mémoire). Savoir les interpréter, souvent en croisant plusieurs sources, est la clé d’un débogage performant.

8. La performance est une ingénierie : concevez, mesurez, itérez.

Le travail sur la performance ne doit jamais être laissé à la fin, surtout à l’échelle macro ou architecturale.

La performance est une caractéristique de conception. Comme la sécurité ou l’ergonomie, la performance doit être prise en compte dès le départ, particulièrement pour les systèmes larges ou complexes. Les choix architecturaux ont l’impact le plus fort et sont les plus difficiles à modifier ensuite.

Suivez un processus itératif. L’optimisation n’est pas une tâche ponctuelle. Elle exige un suivi et un affinage continus tout au long du cycle de vie de l’application.

  1. Définissez objectifs et métriques.
  2. Concevez et implémentez en tenant compte de la performance.
  3. Mesurez par rapport aux objectifs.
  4. Identifiez les goulets d’étranglement.
  5. Optimisez (macro d’abord, puis micro).
  6. Répétez.

Installez une culture de la performance. Sensibilisez votre équipe à la performance. Automatisez tests et surveillance, révisez le code pour détecter les anti-patterns, et priorisez les corrections basées sur les données.

9. Évitez les pièges courants : exceptions, boxing, dynamic, réflexion.

Les exceptions coûtent très cher à lancer.

Les exceptions sont pour les cas exceptionnels. Leur déclenchement engendre un surcoût important (parcours de pile, création d’objets) et ne doit pas servir au contrôle de flux ou aux erreurs attendues. Préférez les méthodes TryParse aux Parse quand le format d’entrée est incertain.

Minimisez le boxing. Enrober un type valeur dans un objet (int vers object) crée des allocations sur le tas et augmente la pression sur le GC. Évitez les API qui boxent implicitement (ex. String.Format avec types valeur, anciennes collections non génériques).

Évitez dynamic et réflexion dans les chemins chauds. Le mot-clé dynamic et les API de réflexion (comme MethodInfo.Invoke) impliquent un coût élevé dû à la résolution de type et à la génération de code à l’exécution. Utilisez-les avec parcimonie, surtout dans le code critique. Si l’invocation dynamique est nécessaire pour la performance, envisagez la génération de code (System.Reflection.Emit) comme alternative.

10. Macro avant micro : privilégiez d’abord l’architecture.

Les optimisations macro sont presque toujours plus bénéfiques que les micro-optimisations.

Priorisez vos efforts d’optimisation. Face à un problème de performance, commencez par examiner les niveaux les plus élevés de votre système :

  • Architecture : le design global est-il efficace ? Utilisez-vous les bonnes technologies ?
  • Algorithmes : les algorithmes principaux sont-ils adaptés à la taille des données et aux modes d’accès (complexité Big O) ?
  • Structures de données : employez-vous des collections et types adaptés à vos usages et besoins mémoire ?

Les micro-optimisations viennent en dernier. Ce n’est qu’après avoir réglé les problèmes de haut niveau que vous devez vous pencher sur les micro-optimisations : affiner des méthodes, réduire de petites allocations, optimiser des boucles courtes. Ces gains sont plus modestes et peuvent masquer des problèmes plus importants si elles sont faites trop tôt.

La séduction de la simplicité : la facilité d’usage de .NET peut inciter à écrire rapidement du code inefficace. Comprendre le coût réel des constructions apparemment simples est essentiel pour ne pas bâtir des systèmes lents à grande vitesse.

Dernière mise à jour:

Avis

4.31 sur 5
Moyenne de 290 évaluations de Goodreads et Amazon.

Writing High-Performance .NET Code bénéficie d’avis positifs, avec une note moyenne de 4,31 sur 5. Les lecteurs apprécient ses conseils pratiques pour optimiser les applications .NET, soulignant son intérêt particulier pour les programmeurs C# avancés. L’ouvrage est salué pour son traitement de divers sujets liés à la performance, tels que la gestion de la mémoire et la compilation JIT. Si certains le jugent indispensable pour les systèmes où la performance est cruciale, d’autres rappellent que toutes les applications ne nécessitent pas un tel niveau d’optimisation. Quelques critiques auraient souhaité des analyses plus approfondies, compte tenu de l’expérience de l’auteur chez Microsoft, mais dans l’ensemble, ce livre reste une ressource fiable pour les développeurs .NET.

Your rating:
4.62
3 évaluations

À propos de l'auteur

Ben Watson travaille chez Microsoft depuis 2008 en tant qu’ingénieur logiciel, spécialisé dans les applications serveur à haute performance. Il a largement contribué à la plateforme Bing en développant un système basé sur .NET capable de gérer un volume important de requêtes à faible latence sur des milliers de machines. Son expertise en optimisation des performances .NET se reflète dans la publication de deux ouvrages techniques. En dehors de son activité professionnelle, il cultive des passions variées telles que le géocaching, la lecture, la musique classique et les moments passés en famille. Son expérience chez Microsoft et son rôle dans la création de systèmes efficaces à grande échelle font de lui une référence incontournable en optimisation des performances .NET.

Listen
Now playing
Writing High-Performance .NET Code
0:00
-0:00
Now playing
Writing High-Performance .NET Code
0:00
-0:00
1x
Voice
Speed
Dan
Andrew
Michelle
Lauren
1.0×
+
200 words per minute
Queue
Home
Library
Get App
Create a free account to unlock:
Recommendations: Personalized for you
Requests: Request new book summaries
Bookmarks: Save your favorite books
History: Revisit books later
Ratings: Rate books & see your ratings
100,000+ readers
Try Full Access for 7 Days
Listen, bookmark, and more
Compare Features Free Pro
📖 Read Summaries
All summaries are free to read in 40 languages
🎧 Listen to Summaries
Listen to unlimited summaries in 40 languages
❤️ Unlimited Bookmarks
Free users are limited to 4
📜 Unlimited History
Free users are limited to 4
📥 Unlimited Downloads
Free users are limited to 1
Risk-Free Timeline
Today: Get Instant Access
Listen to full summaries of 73,530 books. That's 12,000+ hours of audio!
Day 4: Trial Reminder
We'll send you a notification that your trial is ending soon.
Day 7: Your subscription begins
You'll be charged on Jun 22,
cancel anytime before.
Consume 2.8x More Books
2.8x more books Listening Reading
Our users love us
100,000+ readers
"...I can 10x the number of books I can read..."
"...exceptionally accurate, engaging, and beautifully presented..."
"...better than any amazon review when I'm making a book-buying decision..."
Save 62%
Yearly
$119.88 $44.99/year
$3.75/mo
Monthly
$9.99/mo
Start a 7-Day Free Trial
7 days free, then $44.99/year. Cancel anytime.
Scanner
Find a barcode to scan

Settings
General
Widget
Loading...