String concatenation vs String Builder. Performance
Asked Answered
T

10

39

I have a situation where I need to concatenate several string to form an id of a class. Basically I'm just looping in a list to get the ToString values of the objects and then concatenating them.

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

The list is NOT expected to have more than 5 elements (although it could but that's a very, very marginal case) and usually will have from 1 to 3 elements, being common for it to just have one or two.

What would be more performance, keeping the concatenation or using an StringBuilder?

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

I'm unsure if creating the StringBuilder will take more time than standard concatenation for the most usual case.

This is lazy, items on the list do not change once created so the id is lazily constructed once when called.

As a side note... Should I use a fixed array instead of a List? Would I get any performance or memory improvement if I do? (List is only used as an IEnumerable anyway)

A more general view of the question could be, how many strings are enough to stop concatenating and start building?

Should I even bother to test case the scenario?

if (myList.Count > 4) 
  ConcatWithStringBuilder(myList);
Teasley answered 23/10, 2009 at 11:22 Comment(4)
This would be the perfect case for inane micro-optimizing. Don't even bother at this amount of strings.Playoff
Is the possible microseconds difference in time worth your trouble? The time it took you to write this question is probably more than the difference between concat/builder over the life of the program. Especially if it's lazy and only being called once per execution.Cnemis
Possible duplicate of String vs. StringBuilderArmendariz
@JoshSmeaton, that may be true in the OP's given example, but your ignoring the fact that most programmers have to make similar decisions nearly every day, so the OP is likely to apply lessons learned here many hundreds if not thousands of times throughout the life expectancy of .NET.Ethanol
C
44

The usual answer is that string concatenation is more efficient for between 4 to 8 strings. It depends on whose blog you read.

Don't write a test to decide on which method to use. If you are unsure of whether it will go over the magic limit, then just use StringBuilder.

Run this code to see the results for yourself:

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

Complacency answered 23/10, 2009 at 11:26 Comment(4)
i think there is confusion over this subject and it depends who's opinion you respect. The bottom line, from what i understand is that the differences in performance are only really evident when the code is hit often and under significant load.Quarterdeck
@Foxfire: Okay, let's say "an article that presents a couple of different views on what the magic number of concatenations is for making the choice between string and StringBuilder"Complacency
@Aliixx: I completely agree with that. It's also the problem with these things. If you just want a simple rule then you can say if you have LOTS of concats (several 100+) then ALWAYS use StringBuilder. But if you want to give an exact answer then there are a lot of factors coming into the equasion. And it's no longer jsut between 4 and 8. It could as well be 2 or it could be 200 depending on the strings.Wrecker
Wow something seriously weird is happening in .NET Core (Linux). Concatenation took 0.65 seconds, and sb took 0.005 seconds. I even reversed them to see if something weird was happening, but same story. I then put it up to 120 length, 50,000 loops, and concat went up to 156 seconds, and sb to ~0.06 (forgot the exact value, closed the window)Educatee
E
15

I support the idea of keeping things simple until you have a good reason to make them complex.

For something like 2-5 elements there is no point in using the StringBuilder (unless you repeat this concatenation continuously). The better readable syntax "+=" has more value.

Effete answered 23/10, 2009 at 11:25 Comment(5)
Should I even bother to test case the scenario?Carnage
No, I meant like test if the number of objects in the list is greater than X do StringBuilder, oc do concat. I've updated the question body with this :)Carnage
No, not in this case. Unless you're looking at a much higher number of strings, do not sacrifice readability for micro performance increases.Playoff
I would keep it simple. Decide for one or the other option and go with it. No need to do what is called a "premature optimization".Effete
I personally believe that the StringBuilder syntax is more readable, and that the += syntax for String concatentation is masking the creation of a new String object. Personally I think it is better to use String.concat(String) explicitly.Balough
W
9

A more general view of the question could be, how many strings are enough to stop concatenating and start building?

This depends on the length of the strings and if you can predict the target length then you should supply the length to the StringBuilder constructor and if you concatenate them all at once or within several steps.

If you concatenate them at once (like s = "A" + "b" + "c" + "d") then using StringBuilder likely never makes sense.

If you can exactly predict the length then even for 3 Strings StringBuilder would be faster.

Usually StringBuilder is faster if you have more than about 5 concats. But even then just concatenating the Strings usually has little overhead (unless it runs in a tight loop).

As soon as you reach 10 concats using StringBuilder will likely be favorable.

Edit: Just to make it clear: In your case you should clearly go without StringBuilder.

Wrecker answered 23/10, 2009 at 11:32 Comment(0)
D
6

Why can't you just use

String.Concat(myList)

instead of reinventing the wheel? It has high performance and yet is dead simple.
More info here: http://msdn.microsoft.com/en-us/library/system.string.concat.aspx

Deterrence answered 15/9, 2013 at 9:55 Comment(1)
Note in MSDN: You can also use your language's string concatenation operator, such as + in C# and F#, or & and + in Visual Basic, to concatenate strings. Both compilers translate the concatenation operator into a call to one of the overloads of String.Concat.Bram
D
4

IMO string concatenation is more readable. You use + and += instead of strBldInstance.Add() which can muddy the code a little more,

StringBuilder exists to make concatenation more performant, much more, but i usually sacrifice a smidgen of performance for code readability. Your code's not going to affected if you cat a few strings here and there. And for that code block that does cat many strings often, use StringBuilder.

Draco answered 23/10, 2009 at 11:33 Comment(0)
D
1

If you can estimate the number of bytes which will be used for the full string (and use this to initialize the StringBuilder's capacity), the StringBuilder is likely to outperform the String class when doing more than approximately 3 concats.

Delaminate answered 23/10, 2009 at 11:24 Comment(0)
A
0

The string builder will most likely be marginally faster in this case, but really it's probably not going to be enough to fret about. It really is going to depend on two things, the number of times you are re-creating the string (because strings are immutable and joining forces a new string to be created from the two existing ones), and the size of the string elements you are concatenating together. Concatenating five strings which are 2 bytes each is going to be very different than concatenating 5 strings together which are 5000 bytes each, because the the longer the string, the more work the system has to do to allocate memory and garbage collect objects that are no longer in use. The string builder is an all around better bet, because it has already been optimized to join strings together, and you don't really have to worry about performance considerations.

With all of this in mind, if you know about how large the end size of final the string is going to be, string builder will almost certainly be faster. When you tell it how much memory to allocate for the final string, it won't have to go through the process of reallocating memory.

Alister answered 23/10, 2009 at 11:24 Comment(0)
B
0

I'd use StringBuilder just because you want to be consistent throughout an application. Instantiating a Java/.NET object is not time consuming either, although I would guess that there would be some housekeeping upon setup for StringBuilder. Not much worse than creating multiple String objects via concatenation surely.

Balough answered 23/10, 2009 at 11:25 Comment(0)
R
0

If you can, you could have some fun and do away with the for loop altogether and use aggregate?

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

not sure on the overhead of this though?

Ramer answered 23/10, 2009 at 12:44 Comment(1)
Although that's from 7 years ago... Linq is practivally always slower than a direct loop, because it is an inside-out loop with a lot of additional function calls. I tend to think that performance optimisation will always result in throwing Linq out instead of bringing it in.Linq is about readability; not performance...Val
O
0

Found this (performance) topic while solving a leetcode problem. For a string having > 42k (or more) chars, stringBuilder is faster for some reason.

My following code for reversing a string worked in the specified case (> 42k chars) with StringBuilder.

public static string ReverseString(string s)
{
   var toReturn = new StringBuilder();
   for (var i = s.Length - 1; i >= 0; i--)
   {
      toReturn.Append(s[i]);
      }
   return toReturn.ToString();
}

but the same function didn't work with string concatenation i.e. toReturn += s[i].

Orcinol answered 16/1, 2019 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.