2009-10-23 10 views
16

J'ai une situation où j'ai besoin de concaténer plusieurs chaînes pour former un ID d'une classe. Fondamentalement, je suis juste en boucle dans une liste pour obtenir les valeurs ToString des objets, puis les concaténer.Chaîne de concaténation vs String Builder. Performance

foreach (MyObject o in myList) 
    result += o.ToString(); 

La liste ne devrait pas avoir plus de 5 éléments (bien qu'il puisse, mais c'est un très cas marginal) et aura normalement de 1 à 3 éléments, étant communs pour qu'il y ait un seul ou deux.

Qu'est-ce qui serait le plus de performance, en conservant la concaténation ou en utilisant un StringBuilder?

StringBuilder bld = new StringBuilder() 
foreach (MyObject o in myList) 
    bld.Append(o.ToString()); 

Je ne suis pas sûr si la création StringBuilder prendra plus de temps que la concaténation standard pour le cas le plus courant.

Ceci est paresseux, les éléments de la liste ne changent pas une fois créés afin que l'identifiant soit construit paresseusement une fois lorsqu'il est appelé.

En note ... Dois-je utiliser un tableau fixe au lieu d'une liste? Aurais-je une amélioration des performances ou de la mémoire si je le fais? (La liste est seulement utilisée comme IEnumerable de toute façon)

Une vue plus générale de la question pourrait être, combien de chaînes sont suffisantes pour arrêter la concaténation et commencer à construire?

Dois-je même prendre la peine de tester le scénario?

if (myList.Count > 4) 
    ConcatWithStringBuilder(myList); 
+0

Ce serait le cas idéal pour la micro-optimisation inanime. Ne même pas déranger à cette quantité de ficelles. –

+1

Est-ce que la différence de temps en microsecondes possible vaut votre peine? Le temps qu'il vous a fallu pour écrire cette question est probablement plus que la différence entre concat/builder pendant la durée du programme. Surtout si c'est paresseux et seulement appelé une fois par exécution. –

+0

Copie possible de [String vs. StringBuilder] (https://stackoverflow.com/questions/73883/string-vs-stringbuilder) – Matt

Répondre

23

La réponse habituelle est que la concaténation de chaînes est plus efficace pour entre 4 et 8 chaînes. Cela dépend du blog que vous lisez. N'écrivez pas de test pour décider de la méthode à utiliser.

Si vous n'êtes pas sûr de savoir si cela dépassera la limite magique, utilisez simplement StringBuilder.

Exécutez ce code pour voir les résultats pour vous-même:

const int sLen=30, Loops=5000; 
DateTime sTime, eTime; 
int i; 
string sSource = new String('X', sLen); 
string sDest = ""; 
// 
// Time string concatenation. 
// 
sTime = DateTime.Now; 
for(i=0;i<Loops;i++) sDest += sSource; 
eTime = DateTime.Now; 
Console.WriteLine("Concatenation took " + (eTime - sTime).TotalSeconds + " seconds."); 
// 
// Time StringBuilder. 
// 
sTime = DateTime.Now; 
System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1)); 
for(i=0;i<Loops;i++) sb.Append(sSource); 
sDest = sb.ToString(); 
eTime = DateTime.Now; 
Console.WriteLine("String Builder took " + (eTime - sTime).TotalSeconds + " seconds."); 
// 
// Make the console window stay open 
// so that you can see the results when running from the IDE. 
// 
Console.WriteLine(); 
Console.Write("Press Enter to finish ... "); 
Console.Read(); 

Ref. http://support.microsoft.com/kb/306822

+1

Je pense qu'il y a de la confusion sur ce sujet et cela dépend de l'opinion que vous respectez. L'essentiel, d'après ce que je comprends, c'est que les différences de performance ne sont vraiment évidentes que lorsque le code est frappé souvent et sous charge importante. –

+0

@Aliixx: Je suis complètement d'accord. –

+0

@Foxfire: D'accord, disons "un article qui présente quelques vues différentes sur le nombre magique de concaténations pour faire le choix entre chaîne et StringBuilder" –

0

Le constructeur de chaîne sera probablement légèrement plus rapide dans ce cas, mais vraiment il va probablement pas être suffisant pour inquiéter. Cela va vraiment dépendre de deux choses, le nombre de fois que vous recréez la chaîne (parce que les chaînes sont immuables et que vous joignez une nouvelle chaîne à créer à partir des deux existantes), et la taille des éléments de chaîne que vous concaténer ensemble. La concaténation de cinq chaînes de deux octets chacune sera très différente de la concaténation de cinq chaînes de 5000 octets chacune, car plus la chaîne est longue, plus le système doit faire de travail pour allouer de la mémoire et des ordures. plus longtemps en cours d'utilisation. Le générateur de chaînes est un meilleur choix, car il a déjà été optimisé pour joindre des chaînes, et vous n'avez pas vraiment à vous soucier des performances.

Avec tout cela en tête, si vous savez à quel point la taille finale de la chaîne sera grande, le générateur de chaînes sera presque certainement plus rapide. Quand vous lui dites combien de mémoire allouer pour la chaîne finale, il n'aura pas à passer par le processus de réallocation de la mémoire.

0

Si vous pouvez estimer le nombre d'octets qui seront utilisés pour la chaîne complète (et l'utiliser pour initialiser la capacité de StringBuilder), StringBuilder est susceptible de surpasser la classe String en effectuant plus de 3 concatences environ.

11

Je soutiens l'idée de garder les choses simples jusqu'à ce que vous ayez une bonne raison de les complexifier.

Pour quelque chose comme 2-5 éléments, il est inutile d'utiliser StringBuilder (sauf si vous répétez cette concaténation en continu). La meilleure syntaxe "+ =" a plus de valeur.

+0

Dois-je même prendre la peine de tester le scénario? –

+2

Si vous êtes curieux, pourquoi pas? –

+0

Non, je voulais dire comme test si le nombre d'objets dans la liste est plus grand que X font StringBuilder, oc do concat. J'ai mis à jour le corps de la question avec ceci :) –

0

Je voudrais utiliser StringBuilder simplement parce que vous voulez être cohérent dans toute l'application. L'instanciation d'un objet Java/.NET ne prend pas beaucoup de temps non plus, bien que je suppose qu'il y aurait un peu d'entretien lors de l'installation de StringBuilder.Pas beaucoup pire que de créer plusieurs objets String par concaténation sûrement.

3

Une vue plus générale de la question pourrait être, combien de chaînes sont suffisantes pour arrêter la concaténation et commencer à construire?

Cela dépend de la longueur des chaînes et si vous pouvez prédire la longueur cible alors vous devez fournir la longueur au constructeur StringBuilder et si vous les concaténer à la fois ou dans plusieurs étapes.

Si vous les concaténer à la fois (comme s = "A" + "b" + "c" + "d") puis en utilisant StringBuilder fait probablement jamais de sens.

Si vous pouvez prédire exactement la longueur alors même pour 3 Strings StringBuilder serait plus rapide.

Généralement, StringBuilder est plus rapide si vous avez plus de 5 concaves environ. Mais même dans ce cas, la simple concaténation des cordes a généralement peu de frais généraux (à moins que cela ne se fasse dans une boucle serrée).

Dès que vous atteignez 10 concats en utilisant StringBuilder sera probablement favorable.

Éditer: Juste pour être clair: Dans votre cas, vous devriez clairement aller sans StringBuilder.

1

La concaténation de chaîne IMO est plus lisible. Vous utilisez + et + = au lieu de strBldInstance.Add() qui peut un peu bouleverser le code,

StringBuilder existe pour rendre la concaténation plus performante, beaucoup plus, mais je sacrifie habituellement un peu de performance pour la lisibilité du code. Votre code ne va pas être affecté si vous chattez quelques cordes ici et là. Et pour ce bloc de code qui chat souvent plusieurs chaînes, utilisez StringBuilder.

0

Si vous le pouvez, vous pourriez vous amuser et vous débarrasser complètement de la boucle for et utiliser des agrégats?

var concatstring = mylist.Aggregate("", (acc, item) => acc + "." + item); 

pas sûr sur le dessus de ce si?

+1

Bien que cela remonte à 7 ans ... Linq est pratiquement toujours plus lent qu'une boucle directe, car il s'agit d'une boucle à l'envers avec beaucoup d'appels de fonctions supplémentaires. J'ai tendance à penser que l'optimisation des performances aura toujours comme conséquence de jeter Linq au lieu de l'introduire. Linq est sur la lisibilité; pas de performance ... – FrankB