4

Assume I have the following string constants:

const string constString1 = "Const String 1";
const string constString2 = "Const String 2";
const string constString3 = "Const String 3";
const string constString4 = "Const String 4";

Now I can append the strings in two ways: Option1:

string resultString = constString1 + constString2 + constString3 + constString4;

Option2:

string resultString = string.Format("{0}{1}{2}{3}",constString1,constString2,constString3,constString4);

Internally string.Format uses StringBuilder.AppendFormat. Now given the fact that I am appending constant strings, which of the options (option1 or option 2) is better with respect to performance and/or memory?

coder_bro
  • 10,503
  • 13
  • 56
  • 88
  • 7
    this smacks of premature optimization. – nathan gonzalez Mar 02 '11 at 07:11
  • Possible duplicate http://stackoverflow.com/questions/296978/when-is-it-better-to-use-string-format-vs-string-concatenation – Numan Mar 02 '11 at 07:12
  • 1
    @nathan - and of trying to optimize without measuring... – Marc Gravell Mar 02 '11 at 07:17
  • @System.Exception No, different question. Here he's asking of concat of const strings. The "side" effect (how the compiler optimizes it) is interesting enough that a new question is ok. The result (concat is faster than format) is the same, but for another reason. – xanatos Mar 02 '11 at 07:17
  • 1
    @xanatos: There's no technical reason why concat should be faster than format in this case (all strings are constant, including the format string). – Nick Bastin Mar 02 '11 at 07:21
  • @xanatos: I think, I agree with Nick Bastin. Can you give specifics of your findings between the 2 and on what basis you were able to conclude which one is faster? – Numan Mar 02 '11 at 07:24
  • @Nick @System.Exception Because the compiler won't probably unravel and execute the String.Format, in the same way it won't unravel and execute Math.Cos . Compiler unravels and inline only very basic methods. Yeah, it could do it for String.Format, but considering that half of String.Format (not the half used here) is based on the current culture, and that it's probably hundred of rows long... And if you don't trust it, trust the Reflector (just checked). – xanatos Mar 02 '11 at 07:30
  • @Nick @System.Exception as an added bonus, String.Format is in an assembly external to your program. The assembly could change (newer version), so the String.Format could change. – xanatos Mar 02 '11 at 08:43

2 Answers2

11

The first one will be done by the compiler (at least the Microsoft C# Compiler) (in the same way that the compiler does 1+2), the second one must be done at runtime. So clearly the first one is faster.

As an added benefit, in the first one the string is internalized, in the second one it isn't.

And String.Format is quite slow :-) (read this http://msmvps.com/blogs/jon_skeet/archive/2008/10/06/formatting-strings.aspx). NOT "slow enough to be a problem", UNLESS all your program do all the day is format strings (MILLIONS of them, not TENS). Then you could probably to it faster Appending them to a StringBuilder.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Even a C++ compiler could optimize both of these to the same instructions, the CLR JIT should have no trouble coalescing them to the same assemblies. Of course, it might *not* actually do it, but not for lack of information. The only way to know for sure is to test it. – Nick Bastin Mar 02 '11 at 07:16
  • Actually, the optimizations you are referring to here are optimizations done by the C# compiler, and not by the JIT-compiler. – Øyvind Bråthen Mar 02 '11 at 07:17
  • Sure, my point was that even if the CLR compiler didn't do it (which it clearly could, since you have enough information at compile time), it certainly could easily do it at runtime. – Nick Bastin Mar 02 '11 at 07:19
  • @Øyvind Yeah. I have checked it with Reflector and I'm correcting. – xanatos Mar 02 '11 at 07:20
  • I am not so sure about the string interning here. I ran a test indicating that the string is interned also by the `string.Format` scenario (which I found somewhat surprising). – Fredrik Mörk Mar 02 '11 at 07:28
  • @Fredrik No, it isn't: `const string bb = "BBB";const string cc = aa + bb;static string dd = String.Format("{0}{1}", aa, bb);Console.WriteLine(Object.ReferenceEquals(String.Intern(dd), dd));` (the Console is in the Main of a Console Program, everything else is in the Program class) is false... Mmmh but IsInterned and Intern returns different "values"... Strange. – xanatos Mar 02 '11 at 07:39
  • @xanatos: yes I noticed the thing with IsInterned; it returns a string (and not `null` as I expected) for the string created with `string.Format`. Either way, concatenating constants is way faster. – Fredrik Mörk Mar 02 '11 at 07:44
0

The first variant will be best, but only when you are using constant strings.

There are two compilator optimizations (from the C# compiler, not the JIT compiler) that are in effect here. Lets take one example of a program

const string A = "Hello ";
const string B = "World";

...
string test = A + B;

First optimization is constant propagation that will change your code basically into this:

string test = "Hello " + "World";

Then a concatenation of literal strings (as they are now, due to the first optimization) optimization will kick in and change it to

string test = "Hello World";

So if you write any variants of the program shown above, the actual IL will be the same (or at least very similar) due to the optimizations done by the C# compiler.

Øyvind Bråthen
  • 59,338
  • 27
  • 124
  • 151
  • 4
    No, the first version will be best **either way**; with non-literals it will still compile to a single `string.Concat` call, and doesn't need to parse a format string (`"{0}{1}{2}{3}"`) – Marc Gravell Mar 02 '11 at 07:18