Maison  >  Article  >  développement back-end  >  Un aperçu détaillé des améliorations de performances dans .NET

Un aperçu détaillé des améliorations de performances dans .NET

黄舟
黄舟original
2017-03-09 15:41:551498parcourir

.NET 4.6 apporte certaines fonctionnalités CLR liées à l'amélioration des performances. Certaines de ces fonctionnalités prendront effet automatiquement, tandis que d'autres, telles que SIMD et Async Local Storage, nécessitent des modifications dans la façon dont les applications sont écrites.

SIMD

L'équipe Mono a toujours été fière de prendre en charge SIMD, la fonctionnalité de flux de données multiples à flux d'instruction unique. SIMD est un jeu d'instructions CPU capable d'effectuer la même opération sur jusqu'à 8 valeurs en même temps. Avec le lancement de .NET CLR version 4.6, les développeurs Windows peuvent enfin utiliser cette fonctionnalité.

Afin d'observer réellement l'effet du SIMD, vous pouvez vous référer à cet exemple. Supposons que vous deviez ajouter deux tableaux sous la forme c[i] = a[i] b[i] pour obtenir un troisième tableau. En utilisant SIMD, vous pouvez écrire du code de la manière suivante :

for (int i = 0; i < size; i += Vector.Count)
 {
     Vectorv = new Vector(A,i) + new Vector(B,i);
     v.CopyTo(C,i);
 }

Notez comment cette boucle s'incrémente de la valeur de Vectorbd43222e33876353aff11e13a7dc75f6.Count, qui peut être 4 ou 8 selon le type de CPU. Le compilateur .NET JIT générera le code correspondant pour ajouter par lots les tableaux avec une valeur de 4 ou 8 selon le processeur.

Cette méthode semble un peu lourde, c'est pourquoi Microsoft propose également une série de classes auxiliaires, notamment :

  • Structure Matrice3x2

  • Structure Matrix4x4

  • Structure plane

  • Structure quaternion

  • Classe de vecteur

  • Structure du vecteur (T)

  • Structure Vecteur2

  • Structure Vector3

  • Structure Vector4

Désinstallation de l'assemblage

Je crains que la plupart des développeurs ne le sachent pas : .NET charge souvent deux fois le même assembly. La condition pour que cela se produise est que .NET charge d'abord la version IL d'un assembly, puis charge la version NGEN (c'est-à-dire la version précompilée) du même assembly. Cette approche constitue un sérieux gaspillage de mémoire physique, en particulier pour les grandes applications 32 bits telles que Visual Studio.

Dans .NET 4.6, une fois que le CLR charge la version NGEN d'un assembly, il effacera automatiquement la mémoire occupée par la version IL correspondante.

Collecte des déchets

Plus tôt, nous avons discuté du mode de latence du garbage collection introduit dans .NET 4.0. Bien que cette méthode soit beaucoup plus fiable que de laisser le GC s'arrêter complètement pendant un certain temps, elle n'est toujours pas suffisante pour terminer de nombreux scénarios de GC.

Dans .NET 4.6, vous pourrez suspendre temporairement le garbage collector de manière plus sophistiquée. La nouvelle méthode TryStartNoGCRegion vous permet de spécifier la quantité de mémoire nécessaire dans le tas pour les petits objets et les gros objets.

Si la mémoire est insuffisante, le moteur d'exécution renvoie false ou s'arrête jusqu'à ce que suffisamment de mémoire soit obtenue via le nettoyage du GC. Vous pouvez contrôler ce comportement en transmettant un indicateur à TryStartNoGCRegion. Si vous entrez avec succès dans une zone sans GC (le GC n'est pas autorisé avant la fin du processus), la méthode EndNoGCRegion doit être appelée à la fin du processus.

La documentation officielle n'indique pas si cette méthode est thread-safe, mais compte tenu du principe de fonctionnement de GC, vous devriez essayer d'éviter que deux processus tentent de modifier l'état du GC en même temps.

Une autre amélioration apportée au GC réside dans la façon dont il gère les objets épinglés (c'est-à-dire les objets qui ne peuvent pas être déplacés une fois alloués). Bien que cet aspect soit décrit de manière quelque peu vague dans la documentation, lorsque vous fixez la position d'un objet, cela corrige généralement également la position des objets adjacents. Rich Lander a écrit dans l'article :

Le GC gérera les objets épinglés de manière plus optimisée, afin qu'il puisse compresser plus efficacement la mémoire autour des objets épinglés. Pour les applications à grande échelle utilisant un grand nombre de broches, ce changement améliorera considérablement les performances de l'application.

GC fait également preuve d'une meilleure intelligence dans la façon d'utiliser la mémoire dans les générations précédentes. Rich a continué à écrire :

.

La façon dont les objets de génération 1 sont promus en objets de génération 2 a également été améliorée pour utiliser la mémoire plus efficacement. Avant d'allouer un nouvel espace mémoire pour une génération, le GC essaiera d'abord d'utiliser l'espace disponible. Dans le même temps, un nouvel algorithme est utilisé lors de la création d'objets en utilisant l'espace disponible, de sorte que la taille de l'espace nouvellement alloué soit plus proche de la taille de l'objet qu'auparavant.

Stockage local asynchrone

La dernière amélioration n'est pas directement liée aux performances, mais elle permet toujours d'obtenir des résultats d'optimisation grâce à une utilisation efficace. Avant que les API asynchrones ne deviennent populaires, les développeurs pouvaient exploiter le stockage local par thread (TLS) pour mettre en cache les informations. TLS agit comme un objet global pour un thread spécifique, ce qui signifie que vous pouvez accéder directement aux informations contextuelles et les mettre en cache sans avoir à transmettre explicitement un objet contextuel.

En mode asynchrone/attente, le stockage local des threads devient inutile. Parce que chaque fois que wait est appelé, il est possible de passer à un autre thread. Et même si vous parvenez à éviter cette situation, d'autres codes peuvent accéder à votre fil de discussion et interférer avec les informations contenues dans TLS.

La nouvelle version de .NET introduit le mécanisme de stockage local asynchrone (ALS) pour résoudre ce problème. ALS est sémantiquement équivalent au stockage local de thread, mais il peut effectuer les sauts correspondants avec l'appel de wait. Cette fonction sera implémentée via la classe générique AsyncLocal, qui appellera en interne l'objet CallContext pour sauvegarder les données.


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn