What kind of string concatenation should you use?

1 способ: "а" + "b" 2 способ: String.Concat("a","b") 3 способ: StringBuilder db = new StringBuilder("a").Append("b") 

In terms of speed, which method should be used when the lines are small and the joins are small (up to 10 lines)?

What is the way to use when the lines are large?

  • Oh, somewhere there was a good answer to the same question in English, with a small number, they are either equivalent, or + faster. Another clarification question: is it literal strings that add up? or variables? - Grundy
  • 2
    for example Jon Skeet says - + this is the same Concat - Grundy
  • stack of variables! - Leonard Bertone
  • 2
    @Stack, there is an opinion that using Stopwatch also doesn’t help much to get an objective benchmark - Grundy
  • 2
    @Stack, so you can make comparative measurements of only those entities that really differ greatly in performance. Otherwise, all your 100,500 times can be written off for scrap, well, this is if we need a really accurate result. - ixSci

1 answer 1

It is believed that StringBuilder should be used if you have a concatenation of large strings and / or all of this happens in a loop with a large number of iterations. This is due to the fact that the lines are immutable, and therefore each time the line is changed, a new one is actually created. At the same time, StringBuilder deprived of this disadvantage. Here you have a small test, which, however, does not claim to be comprehensively accurate. We have four methods:

  private static long Plus(int counts) { string res = ""; var watch = Stopwatch.StartNew(); for (var i = 0; i < counts; i++) { res = res + DateTime.Now.ToString(); } return watch.ElapsedMilliseconds; } private static long Concat(int counts) { string res = ""; var watch = Stopwatch.StartNew(); for (var i = 0; i < counts; i++) { res = String.Concat(res, DateTime.Now.ToString()); } return watch.ElapsedMilliseconds; } private static long Format(int counts) { string res = ""; var watch = Stopwatch.StartNew(); for (var i = 0; i < counts; i++) { res = String.Format("{0}{1}", res, DateTime.Now.ToString()); } return watch.ElapsedMilliseconds; } private static long Build(int counts) { StringBuilder res = new StringBuilder(); var watch = Stopwatch.StartNew(); for (var i = 0; i < counts; i++) { res = res.Append(DateTime.Now.ToString()); } string res2 = res.ToString(); return watch.ElapsedMilliseconds; } 

The first is for the "normal" addition of strings, the second for String.Concat , the third for String.Format, the fourth for StringBuilder.Append . We run them through a different number of iterations. We get this:

 Plus(1000) - время выполнения 7 мс Concat(1000) - время выполнения 3 мс Format(1000) - время выполнения 8 мс Build(1000) - время выполнения < 1 мс Plus(2000) - время выполнения 13 мс Concat(2000) - время выполнения 11 мс Format(2000) - время выполнения 20 мс Build(2000) - время выполнения 1 мс Plus(5000) - время выполнения 66 мс Concat(5000) - время выполнения 56 мс Format(5000) - время выполнения 133 мс Build(5000) - время выполнения 2 мс Plus(10000) - время выполнения 266 мс Concat(10000) - время выполнения 248 мс Format(10000) - время выполнения 591 мс Build(10000) - время выполнения 5 мс Plus(20000) - время выполнения 1663 мс Concat(20000) - время выполнения 1624 мс Format(20000) - время выполнения 3925 мс Build(20000) - время выполнения 10 мс 

Draw your own conclusions

UPD on a few applications of workers added a method for String.Format. God knows that, but to complete the picture will come down.

  • Another would be to see string.Format :) - Mstislav Pavlov
  • here, in this case, there will be a new line for each addition, while there is no new builder, so it wins :-) try adding a method in which there will be count pluses instead of a cycle - Grundy
  • @ MstislavPavlov, if in a good way to do, then there would be plenty to add. In particular, both String.Format and String.Concat and the + operator have a bunch of different overloads designed for different types and / or number of arguments, which would also be worth considering. Plus, it would not hurt to consider not only the dependence on a different number of iterations, but also on the size of the folding lines, exactly how different methods will behave when adding up to 10, 50, 100, 1000 and so on charactersDreamChild
  • it is better to drive them in parallel. but it turns out because of GC launches at different times. - Stack
  • @Stack sorry, but you are wrong. If you run these four doughs in parallel, the time in the GC spent on garbage collection, which generates the concatenation, will also affect (upwards) the time for string builder. And this can not be called honest tests. If you are embarrassed in a sequential launch that there will be garbage, then the correct test implies garbage collection before running each case. - andreycha