À quel point l'aide d'un StringBuilder devient insignifiant ou une surcharge?
-
23-08-2019 - |
Question
Récemment, je me suis trouvé à l'aide StringBuilder pour tous les concaténations de chaînes, grands et petits, mais dans un récent test de performance, je troqué un collègue de STRINGOUT = string1 + « » chaine2 de style concaténation (utilisé dans une boucle 10000x + avec le StringBuilder étant newed à chaque fois) pour un StringBuilder juste pour voir quelle différence cela ferait dans une concaténation mineure.
J'ai trouvé, sur plusieurs séries de test de performance, le changement était à la fois plus ou moins non significative quel que soit concaténation ou StringBuilder (redisant ce fut pour petits ) concaténations.
À quel point le « newing up » d'un objet StringBuilder nier les avantages de l'utilisation d'un?
La solution
La règle que je suis est -
Utilisez un StringBuilder lorsque le nombre de concaténations est inconnu au moment de la compilation.
Alors, dans votre cas, chaque StringBuilder n'a été quelques fois AJOUT DE, puis d'être mis au rebut. Ce n'est pas vraiment la même chose que quelque chose comme
string s = String.Empty;
for (int i = 0; i < 10000; ++i)
{
s += "A";
}
Si l'aide d'un StringBuilder améliorerait considérablement les performances parce que vous auriez autrement allouez constamment nouvelle mémoire.
Autres conseils
Je suis sûr que j'ai une autre réponse où je Déposée un à mon article et son résumé, mais on y va à nouveau.
-
utiliser Certainement
StringBuilder
lorsque vous concaténer dans une boucle non négligeable - surtout si vous ne savez pas sûr (au moment de la compilation) combien d'itérations vous allez faire à travers la boucle. Par exemple, la lecture d'un fichier un caractère à la fois, la construction d'une chaîne que vous allez en utilisant l'opérateur + = est potentiellement suicide de performance. -
certainement utiliser l'opérateur de concaténation quand vous pouvez (lisiblement) préciser tout ce qui doit être concaténé dans une instruction. (Si vous avez un éventail de choses à concaténer, envisager d'appeler explicitement
String.Concat
-. OuString.Join
si vous avez besoin d'un delimiter) -
Ne pas avoir peur de briser littéraux en plusieurs morceaux concaténés - le résultat sera le même. Vous pouvez faciliter la lecture en brisant un long littérale en plusieurs lignes, par exemple, sans nuire à la performance.
-
Si vous avez besoin des résultats intermédiaires de la concaténation pour autre chose que l'alimentation de la prochaine itération de concaténation,
StringBuilder
ne va pas vous aider. Par exemple, si vous construisez un nom complet d'un prénom et un nom de famille, puis ajouter un troisième élément d'information (le surnom, peut-être) à la fin, vous bénéficiez seulement d'utiliserStringBuilder
si vous ne le besoin (prénom + nom) chaîne à d'autres fins (comme nous le faisons dans l'exemple qui crée un objetPerson
). -
Si vous avez juste quelques concaténations à faire, et que vous voulez vraiment les faire dans des déclarations séparées, il ne compte pas vraiment dans quel sens vous allez. Quelle façon plus efficace dépendra du nombre de concaténations les tailles de chaîne impliqués, et dans quel ordre ils sont concaténés. Si vous croyez vraiment ce morceau de code pour être un goulot d'étranglement de performance, le profil ou le benchmark dans les deux sens.
Parfois, il est intéressant de regarder :
La performance d'une concaténation fonctionnement d'une chaîne ou objet StringBuilder dépend de la souvent une allocation de mémoire se produit. UNE opération de concaténation de chaîne toujours alloue de la mémoire, alors qu'un opération de concaténation StringBuilder seulement si la mémoire alloue un tampon d'objet StringBuilder est trop petite pour accueillir les nouvelles données. Par conséquent, la classe String est de préférence pour une concaténation opération si un nombre fixe de cordes les objets sont concaténés. dans ce cas, l'enchaînement particulier les opérations pourraient même être combinées en une seule opération par le compilateur. UNE objet StringBuilder est préférable une opération de concaténation si un nombre arbitraire de chaînes sont concaténé; Par exemple, si une boucle concatène un nombre aléatoire de chaînes de saisie de l'utilisateur.
Dans votre exemple, il n'y a qu'une seule concaténation par chaîne de sortie, de sorte que StringBuilder vous ne gagne rien. Vous devez utiliser StringBuilder dans les cas où vous ajoutez aux nombreux même chaîne fois, par exemple:.
stringOut = ...
for(...)
stringOut += "."
stringOut += string2
Ma règle de base est simple.
- Si vous pouvez raisonnablement écrire une seule expression qui produit la finale, puis utilisez
+
. - Si vous ne pouvez pas (en raison soit de la taille ou de la variabilité), puis utilisez StringBuilder.
Dans mon expérience, des expressions telles que:
"Id: " + item.id + " name: " + item.name
peut être écrit et compris beaucoup plus facilement que:
StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(item.id);
sb.append(" name: ").append(item.name);
(suivi en utilisant la chaîne de sb
où l'expression ci-dessus aurait été écrit), et il fonctionne aussi bien (indice: regardez le code compilé pour voir pourquoi)
Par contre, quand il y a besoin d'accumuler une chaîne au fil du temps (comme le programme court) ou de l'espace (composé de valeurs provenant de différentes parties du code), d'une manière qui est impossible d'écrire en une seule -ligne expression, puis StringBuilder évite la surcharge (temps et la mémoire-barattage) de:
String s = somethingExpression;
...
s += someOtherExpression;
...
s += yetAnotherExpression;
...
De MSDN :
il classe String est préférable[T] pour un opération de concaténation si un fixe nombre d'objets String sont concaténer. Dans ce cas, la opérations individuelles de concaténation pourrait même être combinés en un seul opération par le compilateur. UNE objet StringBuilder est préférable une opération de concaténation si un nombre arbitraire de chaînes sont concaténé; Par exemple, si une boucle concatène un nombre aléatoire de chaînes de saisie de l'utilisateur.
Je suppose que la réponse est « ça dépend » - si vous concaténer dans une boucle avec plus d'une poignée d'itérations puis un StringBuilder livrera presque toujours de meilleures performances, mais la seule façon de savoir avec certitude est de profil en fait .
Il y a un article intéressant sur ce sur codage Horror. Jeff a obtenu les résultats suivants pour 100.000 itérations sur un dual core 3,5 GHz Core 2 Duo:
Simple Concatenation - 606 ms
String.Format - 665 ms
string.Concat - 587 ms
String.Replace - 979 ms
StringBuilder - 588 ms
De Dot Net Perls :
Quand utiliser StringBuilder?
StringBuilder est tout à fait une optimisation, et il offre aucune amélioration logique de chaîne Concat autre que sa mise en œuvre interne. Cela dit, il est essentiel d'utiliser correctement dans vos applications de haute performance et des sites Web.
Parfois, il est correct d'utiliser de petites boucles de 4 ou moins d'itérations avec concats simples cordes. Cependant, en cas de pointe, cela peut être désastreux. Planifiez votre cas de pointe avec StringBuilder.