Wednesday, May 21, 2008

[C#] More on string concatenation - String.Join

After yesterday's post about "+=" vs StringBuilder, I did a little more looking around on the topic of string concatenation. It appears that if you can get the strings you wish to concatenate into an array then the String.Join(string, string[], int, int) method is actually faster then the StringBuilder.Append method.
public static string Join(
string separator,
string[] value,
int startIndex,
int count
)
Now, in my case, I have a dynamic number of strings I am concatenating together - so using String.Join is a little trickier because I seemingly have to create a List first and then copy over to a String[] before I can use the String.Join method.

My Test - String.Join vs. StringBuilder.Append vs. "+="
I was curious about this, wondering if those intermediate steps would slow things down enough to make String.Join worse than StringBuilder in efficiency... so I wrote up a small little test with timing:
...
int[] numStrings = { 100, 1000, 10000, 20000, 30000 };
foreach (int num in numStrings)
{
output += "*** NUM STRINGS = " + num.ToString() + " ***\r\n";

//---------------------------------
// String.Join
//---------------------------------
start = DateTime.Now;
poo = new List();
for (int i = 0; i < num; i++)
{
poo.Add("poo");
}
newArr = new String[poo.Count];
poo.CopyTo(newArr);
allPoo = String.Join(" ", newArr);
end = DateTime.Now;
diff = end.Subtract(start);
//---------------------------------
start = DateTime.Now;
output += "String.Join: " + diff.ToString() + "\r\n";

//---------------------------------
// StringBuilder.Append
//---------------------------------
newBuilder = new System.Text.StringBuilder();
for (int i = 0; i < num; i++)
{
newBuilder.Append("poo ");
}
end = DateTime.Now;
diff = end.Subtract(start);
//---------------------------------
start = DateTime.Now;
output += "StringBuilder: " + diff.ToString() + "\r\n";

//---------------------------------
// +=
//---------------------------------
myString = "";
for (int i = 0; i < num; i++)
{
myString += "poo ";
}
end = DateTime.Now;
diff = end.Subtract(start);
//---------------------------------
start = DateTime.Now;
output += "+=: " + diff.ToString() + "\r\n";
}
this.oam.addMessage(output);

To which the output was:
*** NUM STRINGS = 100 ***
String.Join: 00:00:00.2031224
StringBuilder: 00:00:00
=: 00:00:00

*** NUM STRINGS = 1000 ***
String.Join: 00:00:00
StringBuilder: 00:00:00
=: 00:00:00.0156248

*** NUM STRINGS = 10000 ***
String.Join: 00:00:00.0156248
StringBuilder: 00:00:00
=: 00:00:01.1249856

*** NUM STRINGS = 20000 ***
String.Join: 00:00:00.0156248
StringBuilder: 00:00:00
=: 00:00:06.5311664

*** NUM STRINGS = 30000 ***
String.Join: 00:00:00.0156248
StringBuilder: 00:00:00.0156248
=: 00:00:16.1404184

So as you can see in this test:
  • StringBuilder.Append only becomes more efficient then String.Join after 1000 strings, although even then the two seem very close in efficiency.
  • "+=" is the least efficient of the group, although it really only becomes noticeable after 1000 strings
My Conclusions
  • I'll probably try to use String.Join where ever possible when doing my large string concatenations, even if I have to place all the strings into a List before I use the method.





1 comment:

jack said...

string.Contat, very useful. Hope your investigation, I know how to use it effectively!