Ssortingng vs SsortingngBuilder

Je comprends la différence entre Ssortingng et SsortingngBuilder ( SsortingngBuilder étant mutable), mais existe-t-il une différence de performance importante entre les deux?

Le programme sur lequel je travaille a beaucoup d’ajouts de chaînes (500+). L’utilisation de SsortingngBuilder un meilleur choix?

Oui, la différence de performance est significative. Consultez l’article de la base de connaissances intitulé « Comment améliorer les performances de concaténation de chaînes dans Visual C # ».

J’ai toujours essayé de coder pour plus de clarté, puis d’optimiser les performances plus tard. C’est beaucoup plus facile que de le faire dans l’autre sens! Cependant, ayant constaté l’énorme différence de performance entre mes deux applications, j’y réfléchis un peu plus attentivement.

Heureusement, il est relativement simple d’exécuter une parsing de performance sur votre code pour voir où vous passez du temps, puis de le modifier pour utiliser SsortingngBuilder si nécessaire.

Pour clarifier ce que Gillian a dit à propos de 4 chaînes, si vous avez quelque chose comme ceci:

 ssortingng a,b,c,d; a = b + c + d; 

alors il serait plus rapide d’utiliser des chaînes et l’opérateur plus. C’est parce que (comme Java, comme le souligne Eric), il utilise en interne automatiquement SsortingngBuilder (en fait, il utilise une primitive que SsortingngBuilder utilise également)

Cependant, si ce que vous faites est plus proche de:

 ssortingng a,b,c,d; a = a + b; a = a + c; a = a + d; 

Ensuite, vous devez utiliser explicitement un SsortingngBuilder. .Net ne crée pas automatiquement un SsortingngBuilder ici, car ce serait inutile. A la fin de chaque ligne, “a” doit être une chaîne (immuable), il faudrait donc créer et disposer un SsortingngBuilder sur chaque ligne. Pour plus de rapidité, vous devez utiliser le même SsortingngBuilder jusqu’à ce que vous ayez créé:

 ssortingng a,b,c,d; SsortingngBuilder e = new SsortingngBuilder(); e.Append(b); e.Append(c); e.Append(d); a = e.ToSsortingng(); 

SsortingngBuilder est préférable si vous faites plusieurs boucles ou des fourchettes dans votre passe de code … cependant, pour des performances PURE, si vous pouvez vous en sortir avec une déclaration de chaîne SINGLE , alors c’est beaucoup plus performant.

Par exemple:

 ssortingng mySsortingng = "Some stuff" + var1 + " more stuff" + var2 + " other stuff" .... etc... etc...; 

est plus performant que

 SsortingngBuilder sb = new SsortingngBuilder(); sb.Append("Some Stuff"); sb.Append(var1); sb.Append(" more stuff"); sb.Append(var2); sb.Append("other stuff"); // etc.. etc.. etc.. 

Dans ce cas, SsortingngBuild pourrait être considéré plus maintenable, mais n’est pas plus performant que la déclaration de chaîne unique.

9 fois sur 10 cependant … utilisez le générateur de chaînes.

Remarque: ssortingng + var est également plus performant que l’approche ssortingng.Format (généralement) qui utilise un SsortingngBuilder en interne (en cas de doute … vérifiez le réflecteur!)

Ce test montre que la concaténation régulière est plus rapide lorsque vous combinez 3 chaînes ou moins.

http://www.chinhdo.com/20070224/ssortingngbuilder-is-not-always-faster/

SsortingngBuilder peut améliorer considérablement l’utilisation de la mémoire, en particulier dans le cas de l’ajout de 500 chaînes.

Prenons l’exemple suivant:

 ssortingng buffer = "The numbers are: "; for( int i = 0; i < 5; i++) { buffer += i.ToString(); } return buffer; 

Que se passe-t-il en mémoire? Les chaînes suivantes sont créées:

 1 - "The numbers are: " 2 - "0" 3 - "The numbers are: 0" 4 - "1" 5 - "The numbers are: 01" 6 - "2" 7 - "The numbers are: 012" 8 - "3" 9 - "The numbers are: 0123" 10 - "4" 11 - "The numbers are: 01234" 12 - "5" 13 - "The numbers are: 012345" 

En ajoutant ces cinq chiffres à la fin de la chaîne, nous avons créé 13 objects chaîne! Et 12 d'entre eux étaient inutiles! Hou la la!

SsortingngBuilder résout ce problème. Ce n'est pas une "chaîne mutable" comme on l'entend souvent ( toutes les chaînes en .NET sont immuables ). Cela fonctionne en gardant un tampon interne, un tableau de caractères. L'appel de Append () ou AppendLine () ajoute la chaîne à l'espace vide à la fin du tableau de caractères; Si le tableau est trop petit, il crée un nouveau tableau plus grand et y copie le tampon. Donc, dans l'exemple ci-dessus, SsortingngBuilder n'a besoin que d'un seul tableau pour contenir les 5 ajouts à la chaîne, en fonction de la taille de son tampon. Vous pouvez indiquer à SsortingngBuilder la taille de son tampon dans le constructeur.

Un exemple simple pour démontrer la différence de vitesse lors de l’utilisation de Ssortingng contactenation vs SsortingngBuilder :

 System.Diagnostics.Stopwatch time = new Stopwatch(); ssortingng test = ssortingng.Empty; time.Start(); for (int i = 0; i < 100000; i++) { test += i; } time.Stop(); System.Console.WriteLine("Using String contactenation: " + time.ElapsedMilliseconds + " milliseconds"); 

Résultat:

Utilisation de la connexion de chaîne: 15423 milliseconds

 SsortingngBuilder test1 = new SsortingngBuilder(); time.Reset(); time.Start(); for (int i = 0; i < 100000; i++) { test1.Append(i); } time.Stop(); System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds"); 

Résultat:

Utilisation de SsortingngBuilder: 10 millisecondes

En conséquence, la première itération a pris 15423 ms tandis que la deuxième itération utilisant SsortingngBuilder duré 10 ms.

Il me semble que l'utilisation de SsortingngBuilder est plus rapide, beaucoup plus rapide.

Ne vous lancez pas aveuglément dans SsortingngBuilder. Il existe des scénarios où SsortingngBuilder n’améliore pas les performances.

Rico Mariani a écrit deux articles de blog perspicaces à ce sujet:

http://blogs.msdn.com/ricom/archive/2003/12/02/40778.aspx

http://blogs.msdn.com/ricom/archive/2003/12/15/43628.aspx

Oui, SsortingngBuilder améliore les performances lors d’opérations répétées sur une chaîne. C’est parce que toutes les modifications sont apscopes à une seule instance, ce qui permet de gagner beaucoup de temps au lieu de créer une nouvelle instance comme Ssortingng .

Ssortingng Vs Ssortingngbuilder

  • Ssortingng

    1. sous System noms System
    2. instance immuable (lecture seule)
    3. la performance se dégrade lorsque le changement de valeur continu se produit
    4. fil sûr
  • SsortingngBuilder (chaîne mutable)

    1. sous l’espace de noms System.Text
    2. instance mutable
    3. affiche de meilleures performances puisque de nouvelles modifications sont apscopes à une instance existante

Recommande fortement l’article de dotnet: Ssortingng Vs SsortingngBuilder en C # .

Question relative au débordement de la stack: Mutabilité de la chaîne lorsque la chaîne ne change pas en C #? .

SsortingngBuilder réduit le nombre d’allocations et d’affectations, au désortingment de la mémoire supplémentaire utilisée. Utilisé correctement, le compilateur n’a plus besoin d’allouer des chaînes de plus en plus grandes jusqu’à ce que le résultat soit trouvé.

 ssortingng result = ""; for(int i = 0; i != N; ++i) { result = result + i.ToSsortingng(); // allocates a new ssortingng, then assigns it to result, which gets repeated N times } 

contre.

 Ssortingng result; SsortingngBuilder sb = new SsortingngBuilder(10000); // create a buffer of 10k for(int i = 0; i != N; ++i) { sb.Append(i.ToSsortingng()); // fill the buffer, resizing if it overflows the buffer } result = sb.ToSsortingng(); // assigns once 

Les performances d’une opération de concaténation pour un object Ssortingng ou SsortingngBuilder dépendent de la fréquence à laquelle une allocation de mémoire se produit. Une opération de concaténation de chaînes alloue toujours de la mémoire, tandis qu’une opération de concaténation SsortingngBuilder n’alloue la mémoire que si le tampon d’objects SsortingngBuilder est trop petit pour accueillir les nouvelles données. Par conséquent, la classe Ssortingng est préférable pour une opération de concaténation si un nombre fixe d’objects Ssortingng est concaténé. Dans ce cas, les opérations de concaténation individuelles peuvent même être combinées en une seule opération par le compilateur. Un object SsortingngBuilder est préférable pour une opération de concaténation si un nombre arbitraire de chaînes est concaténé; Par exemple, si une boucle concatène un nombre aléatoire de chaînes de saisie utilisateur.

Source: MSDN

SsortingngBuilder est préférable pour créer une chaîne à partir de nombreuses valeurs non constantes.

Si vous construisez une chaîne à partir d’un grand nombre de valeurs constantes, telles que plusieurs lignes de valeurs dans un document HTML ou XML ou d’autres morceaux de texte, vous pouvez vous contenter de les append à la même chaîne, car presque tous les compilateurs le font. “pliage constant”, un processus de réduction de l’arbre d’parsing lorsque vous manipulez constamment (il est également utilisé lorsque vous écrivez quelque chose comme int minutesPerYear = 24 * 365 * 60 ). Et pour les cas simples avec des valeurs non constantes ajoutées les unes aux autres, le compilateur .NET réduira votre code à un niveau similaire à celui de SsortingngBuilder .

Mais lorsque votre append ne peut pas être réduit à quelque chose de plus simple par le compilateur, vous voudrez un SsortingngBuilder . Comme le souligne Fizch, il est plus probable que cela se produise à l’intérieur d’une boucle.

Je pense que SsortingngBuilder est plus rapide si vous devez append plus de 4 chaînes. De plus, il peut faire des choses sympas comme AppendLine.

Dans .NET, SsortingngBuilder est toujours plus rapide que l’ajout de chaînes. Je suis presque sûr qu’en Java, ils créent juste un SsortingngBuffer sous le capot lorsque vous ajoutez des chaînes, donc il n’y a pas vraiment de différence. Je ne sais pas pourquoi ils ne l’ont pas encore fait dans .NET

Considérez la tragédie sortingste du théâtre de micro-optimisation .

L’utilisation de chaînes pour la concaténation peut entraîner une complexité d’exécution de l’ordre de O(n^2) .

Si vous utilisez un SsortingngBuilder , il y a beaucoup moins de copies de mémoire à faire. Avec SsortingngBuilder(int capacity) vous pouvez augmenter les performances si vous pouvez estimer la taille de la Ssortingng finale. Même si vous n’êtes pas précis, vous devrez probablement augmenter la capacité de SsortingngBuilder à quelques resockets, ce qui peut également améliorer les performances.

L’utilisation de la EnsureCapacity(int capacity) sur une instance de SsortingngBuilder avant de l’utiliser pour tout stockage de chaînes a EnsureCapacity(int capacity) gains de performances significatifs. Je l’appelle habituellement sur la ligne de code après l’instanciation. Il a le même effet que si vous instanciez le SsortingngBuilder comme ceci:

 var sb = new SsortingngBuilder(int capacity); 

Cet appel alloue la mémoire nécessaire à l’avance, ce qui entraîne moins d’allocations de mémoire lors de plusieurs opérations Append() . Vous devez faire une estimation éclairée de la quantité de mémoire dont vous aurez besoin, mais pour la plupart des applications, cela ne devrait pas être trop difficile. J’ai l’habitude de faire un peu trop de mémoire (on parle de 1k environ).

Suite aux réponses précédentes, la première chose que je fais toujours lorsque je pense à des problèmes comme celui-ci est de créer une petite application de test. Dans cette application, effectuez un test de synchronisation pour les deux scénarios et voyez par vous-même lequel est le plus rapide.

À mon humble avis, append plus de 500 entrées de chaîne devrait certainement utiliser SsortingngBuilder.

Ssortingng et SsortingngBuilder sont en fait tous les deux immuables, le SsortingngBuilder a des tampons intégrés qui permettent de gérer plus efficacement sa taille. Lorsque SsortingngBuilder doit être redimensionné, c’est quand il est ré-alloué sur le tas. Par défaut, il est dimensionné à 16 caractères, vous pouvez le définir dans le constructeur.

par exemple.

SsortingngBuilder sb = new SsortingngBuilder (50);

La concaténation de chaînes vous coûtera plus cher. En Java, vous pouvez utiliser SsortingngBuffer ou SsortingngBuilder en fonction de vos besoins. Si vous souhaitez une implémentation synchronisée et thread-safe, optez pour SsortingngBuffer. Ce sera plus rapide que la concaténation Ssortingng.

Si vous n’avez pas besoin d’implémentation synchronisée ou Thread, optez pour SsortingngBuilder. Ce sera plus rapide que la concaténation de chaînes et plus rapide que SsortingngBuffer car il n’y a pas de surcharge de synchronisation.

SsortingngBuilder est probablement préférable. La raison en est qu’elle alloue plus d’espace que nécessaire (vous définissez le nombre de caractères) pour laisser de la place aux ajouts futurs. Ensuite, les futurs ajouts qui rentrent dans le tampon actuel ne nécessitent aucune allocation de mémoire ou récupération de mémoire, ce qui peut être coûteux. En général, j’utilise SsortingngBuilder pour la concaténation de chaînes complexes ou la mise en forme multiple, puis convertis en une chaîne normale lorsque les données sont complètes et que je souhaite un nouvel object immuable.

Si vous faites beaucoup de concaténation de chaîne, utilisez un SsortingngBuilder. Lorsque vous concaténez avec une chaîne, vous créez une nouvelle chaîne à chaque fois, en utilisant plus de mémoire.

Alex

En règle générale, si je dois définir la valeur de la chaîne plus d’une fois, ou s’il y a des ajouts à la chaîne, il doit s’agir d’un générateur de chaînes. J’ai vu des applications que j’ai écrites dans le passé avant d’en apprendre plus sur les constructeurs de chaînes de caractères qui ont eu un énorme empreinte de mémoire qui semble continuer à croître et à croître. La modification de ces programmes pour utiliser le générateur de chaînes réduit considérablement l’utilisation de la mémoire. Maintenant, je jure par le constructeur de cordes.

Mon approche a toujours été d’utiliser SsortingngBuilder lors de la concaténation de 4 chaînes ou plus OU lorsque je ne sais pas comment les concaténations doivent avoir lieu.

Bon article sur la performance ici

SsortingngBuilder est beaucoup plus efficace, mais vous ne verrez pas cette performance à moins que vous ne modifiiez beaucoup les chaînes.

Vous trouverez ci-dessous une partie rapide du code pour donner un exemple de la performance. Comme vous pouvez le constater, vous commencez vraiment à voir une augmentation majeure des performances lorsque vous vous lancez dans de grandes itérations.

Comme vous pouvez le voir, les 200 000 itérations ont pris 22 secondes alors que les 1 million d’itérations utilisant SsortingngBuilder été presque instantanées.

 ssortingng s = ssortingng.Empty; SsortingngBuilder sb = new SsortingngBuilder(); Console.WriteLine("Beginning Ssortingng + at " + DateTime.Now.ToSsortingng()); for (int i = 0; i <= 50000; i++) { s = s + 'A'; } Console.WriteLine("Finished String + at " + DateTime.Now.ToString()); Console.WriteLine(); Console.WriteLine("Beginning String + at " + DateTime.Now.ToString()); for (int i = 0; i <= 200000; i++) { s = s + 'A'; } Console.WriteLine("Finished String + at " + DateTime.Now.ToString()); Console.WriteLine(); Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString()); for (int i = 0; i <= 1000000; i++) { sb.Append("A"); } Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString()); Console.ReadLine(); 

Résultat du code ci-dessus:

Début Ssortingng + au 28/01/2013 16:55:40.

Terminé Ssortingng + au 28/01/2013 16:55:40.

Début Ssortingng + au 28/01/2013 16:55:40.

Terminé Ssortingng + au 28/01/2013 16:56:02.

Début Sb annexe au 28/01/2013 16:56:02.

Terminé Sb append au 28/01/2013 16:56:02.

SsortingngBuilder sera plus performant, du sharepoint vue de la mémoire. En ce qui concerne le traitement, la différence de temps d’exécution peut être négligeable.