7

Which way to create strings is more run time efficient in C#

Number 1:

bool value = true;
int channel = 1;
String s = String.Format(":Channel{0}:Display {1}", channel, value ? "ON" : "OFF");

Number 2:

bool value = true;
String channel = "1";
string  s = ":Channel" + channel + ":Display " + value ? "ON" : "OFF";
Razer
  • 7,843
  • 16
  • 55
  • 103
  • I realize that I'm asking almost impossible thing but WHY haven't you tried to measure yourself? – zerkms Mar 10 '13 at 21:28
  • 2
    Have you identified this as a performance problem? Pick the more readable one (IMO `Format`) – Andrew Whitaker Mar 10 '13 at 21:28
  • Why the downvotes? It's a decent question (even though you could measure it yourself; otoh, it could help others) – Bart Friederichs Mar 10 '13 at 21:30
  • Note that the first version starts with a colon; the second doesn't. – Jon Skeet Mar 10 '13 at 21:31
  • 2
    @Bart Friederichs: performance issues often have nothing in common. It's often a bad idea to try solving your own performance issues following others' solutions, just because even a tiny difference in the environment may bring a huge difference in results. – zerkms Mar 10 '13 at 21:32
  • 1
    No don't have a performance problem. I know preoptimization is the root of all evil. But I'm coming from other hardware where performance is rare. If I implement something new, it doesn't matter if I do it this way or that way - so I can do it right the first time. All changes afterwards sucks... – Razer Mar 10 '13 at 21:38
  • Hi Razor, I will not join the discussion, but this link might give you some pointers which approach to use when : http://geekswithblogs.net/BlackRabbitCoder/archive/2010/05/10/c-string-compares-and-concatenations.aspx – bas Mar 10 '13 at 21:42
  • In most code either will be fine; the first has some extra parsing, but when I've tested it that parsing is so fast that it simply doesn't impact the results. The first approach will be much easier to internationalize / localize if you need to. The second has less parsing, but higher maintenance cost (trickier to internationalize etc). – Marc Gravell Mar 10 '13 at 21:43
  • Option 2 doesn't even compile – DGibbs Mar 10 '13 at 21:44
  • 1
    @DGibbs true; I assume it should be `string s = ":Channel" + channel + ":Display " + (value ? "ON" : "OFF");` – Marc Gravell Mar 10 '13 at 21:45
  • possible duplicates: http://stackoverflow.com/questions/296978/when-is-it-better-to-use-string-format-vs-string-concatenation and http://stackoverflow.com/questions/16432/c-sharp-string-output-format-or-concat – bas Mar 10 '13 at 21:46
  • This is a question that's been asked dozens of times. http://stackoverflow.com/questions/21078/whats-the-best-string-concatenation-method-using-c gives a good overview and heuristics with which to choose. – Avner Shahar-Kashtan Mar 10 '13 at 21:47
  • 1
    The first is far better regardless of its performance: *the first technique allows you to isolate the string into a localizable resource*. – Eric Lippert Mar 10 '13 at 22:26

4 Answers4

7

I'm going to add an example now to illustrate how the compiler treats the two, because there seems to be a lot of confusion in some of the other answers (edit: note that much of these confusions have now been deleted/edited away):

bool value = true;
int channel = 1;
String s = String.Format(":Channel{0}:Display {1}", channel,
    value ? "ON" : "OFF");

The last line is compiled as:

String s = String.Format(":Channel{0}:Display {1}",
    new object[2] {(object)channel, value ? "ON" : "OFF")};

note interestingly the creation of an array and a "box" for int channel, and of course the extra parsing required to find {0} / {1}.

Now Number 2:

bool value = true;
String channel = "1";
string  s = ":Channel" + channel + ":Display " + (value ? "ON" : "OFF");

The last line is compiled as:

string s = string.Concat(":Channel", channel, ":Display ", value ? "ON" : "OFF");

here there is no array, no box (channel is now a string), and no parsing. The overload is public static string string.Concat(string,string,string,string); string.Concat is implemented very efficiently, pre-allocating a right-sized string in advance then over-writing, etc.

In most code, either is fine. The second version is technically more efficient (no box, no array, no parsing), but is a major pain if you ever want to internationalize later. In most applications you will not notice any difference between the two. The parsing is fast, and the box / array are collected cheaply as gen-zero objects. But cheap is not free.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
6

This could help you to test this yourself. This was executed using .net v4.0.30319 runtime.

sw = new System.Diagnostics.Stopwatch();

// Number 1
bool value = true;
int channel = 1;
sw.Start();
for (int i = 0; i <= 100000; i++)
{
    String s = String.Format(":Channel{0}:Display {1}", channel, value ? "ON" : "OFF");
}
sw.Stop();

sw.Reset();

// Number 2
sw.Start();
for (int i = 0; i <= 100000; i++)
{
    string s = "Channel" + channel + ":Display " + (value ? "ON" : "OFF");
}
sw.Stop();

My result is:

Number 1: 136ms

Number 2: 91ms

So the second option has better performance. The fact that the first option uses an extra method call (string.Format()) and replacing parameters (as Marc remarked) is what makes the difference.

If instead of using 100.000 iterations I use 1.000.000, this is what I get

Number 1: 1308ms

Number 2: 923ms

Basically, same conclusion.

Community
  • 1
  • 1
Claudio Redi
  • 67,454
  • 15
  • 130
  • 155
  • 1
    Personally I don't this 16ms vs 12ms is clear cut enough, given timing accuracy – Marc Gravell Mar 10 '13 at 21:46
  • @MarcGravell: Sorry, while you were writing this comment I was adding another example with 100.000 iterations. – Claudio Redi Mar 10 '13 at 21:49
  • 1
    That's more like it ;) now all you have to do is run it on the OP's exact .NET (sub-)version, OS (sub-)version, and exact hardware, under exactly the same background load conditions... (ok, I'm teasing now) – Marc Gravell Mar 10 '13 at 21:53
  • @MarcGravell: IMHO the result seems to be pretty conclusive for the same .net runtime. The execution times may change from machine to machine but 2nd option is more efficient (at least from time execution point of view) taking into account the big difference showed on my test. – Claudio Redi Mar 10 '13 at 22:06
  • Indeed; and like I said already - it is much better with those numbers; the 12 vs 16... not very conclusive – Marc Gravell Mar 10 '13 at 22:08
  • @Marc Gravell: agreed, removed to avoid confusions. Thanks for the feedback! – Claudio Redi Mar 10 '13 at 22:09
0

Regarding Marc Gravell's answer: You can avoid the boxing operation by passing channel.ToString(). I have verified emperically that this gives a slight performance improvement for both #1 and #2.

  • In case #1, you avoid the boxing operation.
  • In case #2, you avoid calling the implicit conversion operator.

But after trying to disprove your theory, (with longer concatenations and random strings) I must concede that #2 is faster than #1.

Adam C
  • 20
  • 4
-4

Number 1 is the most efficient.

String.Format() function uses System.Text.StringBuilder type internally for concatenating strings.

The StringBuilder is used to represent a mutable(aka editable) strings and it is the most efficient way to concatinate strings. http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx.

Georgii Gonchar
  • 436
  • 2
  • 4
  • 1
    that reasoning is incomplete; the second version uses `string.Concat`, which is *also* heavily optimized. Arguably even more so, since it uses a fast-alloc and overwrite approach, rather than a resized backing buffer. If this was a loop, then sure: `StringBuilder` would win hands down. For a single-line concat: no; `string.Concat` is the most appropriate approach, which can be done using the code shown in the 2nd example. – Marc Gravell Mar 10 '13 at 21:50
  • From [MSDN](http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx) `Use the String class if you are concatenating a fixed number of String objects. In that case, the compiler may even combine individual concatenation operations into a single operation.` – Dzienny Mar 10 '13 at 21:57
  • 1
    Your edit makes this answer worse and actively incorrect. Sorry, but I don't think you understand how the compiler treats the 2nd example. Hint: it isn't what you describe. – Marc Gravell Mar 10 '13 at 21:58
  • This is the except from Microsoft guide of using string.Concat() : "... when performance is important, you should always use the StringBuilder class to concatenate strings. ..." http://msdn.microsoft.com/en-us/library/ms228504.aspx – Georgii Gonchar Mar 10 '13 at 21:59
  • As a general rule of thumb , StringBuilder is only more efficient in cases where you're concatenating very large strings, or very large numbers of strings, perhaps inside of a loop. Something like "Hello" + "World" will boil down to `String.Concat` which is far better suited to this scenario since we already know the size of the strings before compile time and don't need dynamic resizing that Stringbuilder provides – DGibbs Mar 10 '13 at 22:00
  • @GeorgiiGonchar search that page for "Even if you use several + operators in one statement, the string content is copied only once."; what you say is true only when there are multiple statements. Here there is only one. Sorry, but your example is incorrect and does not apply here. – Marc Gravell Mar 10 '13 at 22:04
  • @MarcGravell agree with your point. I didn't understood the question correctly and answered too soon. Lesson learned. – Georgii Gonchar Mar 10 '13 at 22:26