Cet article est un article miroir de traduction automatique, veuillez cliquer ici pour accéder à l’article original.

Vue: 6846|Répondre: 2

[Source] [Tourne]. Optimisation des performances .NET - Collections. Pooled est recommandé

[Copié le lien]
Publié le 29-05-2022 à 13:45:22 | | | |
Brève introduction

L’optimisation des performances consiste à garantir que le même nombre de requêtes soit traité avec moins de ressources, généralement du CPU ou de la mémoire, et bien sûr, des gestions d’E/S du système d’exploitation, du trafic réseau, de l’utilisation du disque, etc. Mais la plupart du temps, nous réduisons la consommation de CPU et de mémoire.
Le contenu partagé auparavant présente certaines limites, il est difficile de le transformer directement, aujourd’hui je souhaite vous présenter une méthode simple : il suffit de remplacer quelques types de collections, pour obtenir l’effet d’amélioration des performances et de réduction de l’empreinte mémoire.
Aujourd’hui, je veux vous présenter une bibliothèque de classe, ceciLa bibliothèque de classes s’appelle Collections. Pooled, Comme on peut le voir dans son nom, c’est grâce à la mémoire poolée pour atteindre l’objectif de réduire l’empreinte mémoire et la GC, et nous verrons directement ses performances, et nous vous emmènerons également voir le code source, pourquoi il apporte ces améliorations de performance.

Collections.Pooled

Lien du projet :La connexion hyperlientérée est visible.

La bibliothèque est basée sur des classes dans System.Collections.Generic, qui ont été modifiées pour tirer parti des nouvelles bibliothèques de classes System.Span <T>et System.Buffers.ArrayPool <T>dans le but de réduire l’allocation mémoire, d’améliorer les performances et de permettre une meilleure interopérabilité avec les API modernes.
Collections.Pooled prend en charge .NET Standnd 2.0 (.NET Framework 4.6.1+), ainsi que la prise en charge de . NET Core 2.1+. Un vaste ensemble de tests unitaires et de benchmarks a été porté depuis CoreFX.

Nombre total de tests : 27501. Via : 27501. Échec : 0. Skip : 0.
L’essai a été un succès.
Temps d’exécution du test : 9,9019 secondes

Comment utiliser

Vous pouvez facilement installer cette bibliothèque via Nuget, NuGet Version.

Dans la bibliothèque Collections.Pooled, il implémente des versions regroupées pour les types de collections que nous utilisons couramment, comme le montre la comparaison avec les types natifs .NET.

. .NET natifCollections.Pooledremarque
Liste<T>PooledList<T>Classes de collections génériques
Dictionnaire<TKey, TValue>Dictionnaire Poolé<TKey, TValue>Classe de dictionnaire générique
HashSet<T>PooledSet<T>Classes de collections de hachages génériques
Pile<T>Pile<T>Piles génériques
Queue<T>PooledQueue<T>Cohorte générique

Lorsqu’on utilise, il suffit d’ajouter le fichier correspondant . .NET avec la version Collections.Pooled, comme indiqué dans le code ci-dessous :

Cependant, il faut noter que le type Pooled implémente l’interface IDispose, qui renvoie la mémoire utilisée au pool via la méthode Dispose(), donc nous devons appeler sa méthode Dispose() après avoir utilisé l’objet de collection Pooled. Ou vous pouvez utiliser directement le mot-clé using var.

Note : Utilisez l’objet collection à l’intérieur de Collections.PooledIl est préférable de devoir le libérer manuellement, mais peu importe si vous ne le libérez pas, le GC finira par le recycler, mais il ne peut pas être retourné dans le pool, et cela n’aura pas l’effet de sauvegarder la mémoire.
Puisqu’il réutilise l’espace mémoire, lorsqu’il retourne de l’espace mémoire au pool, il doit traiter les éléments de la collection, et il fournit une énumération appelée ClearMode à utiliser, définie comme suit :




Par défaut, vous pouvez utiliser la valeur par défaut Auto, et s’il y a des exigences de performance particulières, vous pouvez utiliser Never après avoir connu les risques.
Pour les types de référence et les types de valeur contenant des types de référence, il faut vider la référence du tableau lors du retour de l’espace mémoire au pool, si ce n’est pas effacé, le GC ne pourra pas libérer cette partie de l’espace mémoire (car la référence de l’élément a toujours été détenue par le pool), si c’est un type à valeur pure, alors il ne peut pas être vidé ; dans cet article, je décris la différence de stockage entre les types de référence et les tableaux de type struct (type de valeur), les types à valeur pure n’ont pas de recyclage d’en-tête d’objet et ne nécessitent pas d’intervention de GC.


. Optimisation des performances .NET - Utilisez des classes alternatives struct :La connexion hyperlientérée est visible.

Comparaison des performances

Je n’ai pas fait Benchmark seul, et les résultats de score des projets open source que j’ai directement utilisés étaient de 0 pour l’utilisation de la mémoire de nombreux projets, car la mémoire en pool utilisée n’avait pas d’allocation supplémentaire.

PooledList<T>

En boucle les 2048 éléments ajoutés à l’ensemble dans Benchmark, . .NET native List <T>nécessite 110us (selon les résultats réels du benchmark, les millisecondes dans la figure devraient être une erreur administrative) et 263 Ko de mémoire, tandis que PooledList <T>n’a besoin que de 36 us et 0 KB de mémoire.




Dictionnaire Poolé<TKey, TValue>

Ajoutez 10_0000 éléments au dictionnaire dans une boucle dans Benchmark, . .NET native Dictionary<TKey, TValue> nécessite 11 ms et 13 Mo de mémoire, tandis que PooledDictionary<TKey, TValue> ne nécessite que 7 ms et 0 Mo de mémoire.




PooledSet<T>

En boucle dans la collection de hachages dans Benchmark, ajoutez 10_0000 éléments, . Le HashSet natif .<T>NET nécessite 5348 ms et 2 Mo, tandis que le PooledSet <T>ne nécessite que 4723 ms et 0 Mo de mémoire.




PooledStack<T>

Boucle dans la pile dans Benchmark pour ajouter 10_0000 éléments, . Le PooledStack natif <T>.NET nécessite 1079 ms et 2 Mo, tandis que PooledStack <T>ne nécessite que 633 ms et 0 Mo de mémoire.




PooledQueue<T>

Boucle les boucles dans Benchmark pour ajouter 10_0000 éléments à la file d’attente, . <T>La PooledQueue native .NET nécessite 681 ms et 1 Mo, tandis que la PooledQueue <T>ne nécessite que 408 ms et 0 Mo de mémoire.




La scène n’est pas publiée manuellement

De plus, nous avons mentionné plus haut que le type de collecte regroupée doit être publié, mais cela n’a pas d’importance s’il ne l’est pas, car le GC recyclera.


Les résultats du benchmark sont les suivants :



La conclusion peut être tirée des résultats du Benchmark ci-dessus.

Libérer la collection de types Pooled à temps déclenche à peine GC et alloue de la mémoire, d’après le graphique ci-dessus, il n’alloue que 56 octets de mémoire.
Même si la collection de types Pooled n’est pas publiée, car elle alloue de la mémoire du pool, elle réutilisera tout de même la mémoire lors de l’expansion ReSize et passera l’étape d’initialisation de l’allocation mémoire GC, qui est relativement rapide.
Le plus lent est d’utiliser le type de collection normal, chaque opération d’extension ReSize doit demander un nouvel espace mémoire, et le GC doit également récupérer l’espace mémoire précédent.


Analyse des principes

Si vous avez lu mon précédent article de blog, vous devriez définir la taille initiale des types de collections et analyser le principe d’implémentation du dictionnaire C# ; vous pouvez savoir que les développeurs BCL .NET utilisent les structures de données sous-jacentes de ces types de collections de base comme tableaux pour un accès aléatoire haute performance, prenons List <T>comme exemple.

Créez un nouveau tableau pour stocker les éléments ajoutés.
S’il n’y a pas assez d’espace dans le tableau, l’opération d’expansion est déclenchée pour demander deux fois la taille de l’espace.
Le code constructeur est le suivant, et vous pouvez voir qu’il s’agit d’un tableau générique créé directement :


Donc, si vous voulez mettre en pool de la mémoire, il suffit de changer l’endroit où la nouvelle application de mots-clés est utilisée dans la bibliothèque de classes pour utiliser une application en pool. Ici, je le partage avec vous. NET BCL est un type appelé ArrayPool, qui fournit un pool de ressources de tableaux d’instances génériques réutilisables, pouvant être utilisées pour réduire la pression sur GC et améliorer les performances en cas de création et destruction fréquentes de tableaux.

La couche sous-jacente de notre type Pooled est d’utiliser ArrayPool pour partager des pools de ressources, et à partir de son constructeur, on peut voir qu’il utilise ArrayPool par défaut<T>. Partagé pour assigner des objets de tableau, et bien sûr vous pouvez aussi créer votre propre ArrayPool pour l’utiliser.


De plus, lors d’une opération d’ajustement de capacité (expansion), l’ancien tableau est retourné au pool de threads, et le nouveau tableau est également acquis auprès du pool.

De plus, l’auteur utilise Span pour optimiser des API telles que Ajouter et Insérer afin d’obtenir de meilleures performances en accès aléatoire. De plus, l’API de la série TryXXX a été ajoutée, ce qui vous permet de l’utiliser de manière plus pratique. Par exemple, la <T>classe List <T>comporte jusqu’à 170 modifications par rapport à PooledList.



résumé

Dans notre utilisation en ligne réelle, nous pouvons remplacer le type de collection natif par le type de collection fourni par Pooled, ce qui est très utile pour réduire la consommation de mémoire et la latence de P95.
De plus, même si vous oubliez de le sortir, les performances ne seront pas beaucoup moins bonnes que d’utiliser le type de collection natif. Bien sûr, la meilleure habitude est de la libérer à temps.


Langue source:La connexion hyperlientérée est visible.




Précédent:RecyclableMemoryStream offre un streaming .NET haute performance
Prochain:[Combat pratique] Le serveur construit LibreSpeed pour tester la vitesse du réseau
Publié le 29-05-2022 à 17:12:36 |
Apprends-le
Publié le 20-06-2022 09:09:22 |
Apprenez le mix
Démenti:
Tous les logiciels, supports de programmation ou articles publiés par Code Farmer Network sont uniquement destinés à l’apprentissage et à la recherche ; Le contenu ci-dessus ne doit pas être utilisé à des fins commerciales ou illégales, sinon les utilisateurs assumeront toutes les conséquences. Les informations sur ce site proviennent d’Internet, et les litiges de droits d’auteur n’ont rien à voir avec ce site. Vous devez supprimer complètement le contenu ci-dessus de votre ordinateur dans les 24 heures suivant le téléchargement. Si vous aimez le programme, merci de soutenir un logiciel authentique, d’acheter l’immatriculation et d’obtenir de meilleurs services authentiques. En cas d’infraction, veuillez nous contacter par e-mail.

Mail To:help@itsvse.com