Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StringBuilder and '+' operator

Im maintaining thise code here which often has a pattern like the following:

StringBuilder result = new StringBuilder();

result.Append("{=" + field.Name + "={");

It seems like a waste with a lot of useless object construction when doing it like this and I want to rewrite to this:

result.Append("{=").Append(field.Name).Append("={");

Is it correct that the first version is putting more strain on the GC? Or is there some optimization in the C# compiler with string literals where concatenating string's with string literals does not create temporary objects?

like image 432
Serve Laurijssen Avatar asked May 26 '14 13:05

Serve Laurijssen


People also ask

What is difference between StringBuilder and StringBuffer?

String is immutable whereas StringBuffer and StringBuilder are mutable classes. StringBuffer is thread-safe and synchronized whereas StringBuilder is not. That's why StringBuilder is faster than StringBuffer. String concatenation operator (+) internally uses StringBuffer or StringBuilder class.

Is StringBuilder better than concatenation?

Conclusion. StringBuilder executes significantly faster than the String class when performing the concatenation or modification operations. Modifying a String creates a new String in the heap memory. To change the content of the String, we should consider the StringBuilder class.

What is faster than StringBuilder?

For less than 6 concatenations, using regular strings is actually faster than using stringbuilders! The reason is that setting up the buffer space and then converting it back to a string introduces a bit of overhead.

Can we concatenate string and StringBuilder in Java?

String concatenation using StringBuilder class The append() method accepts arguments of different types like Objects, StringBuilder, int, char, CharSequence, boolean, float, double. StringBuilder is the most popular and fastet way to concatenate strings in Java.


2 Answers

I agree with all the answers, but to me you need to understand strings in C# and they way they are actually manipulated 'under the covers'

The use of a StringBuilder comes in to its own when 5 or more strings are being concatenated. This is because the compiler intrinsically converts:

string a = b + c + d + e + f;

into

r = String.Concat(new String[5] { a, b, c, d, e });

so there is an implicit overhead of array creation.

I would suggest reading the following by Eric Lippert who wrote string concatenation in C#:
http://ericlippert.com/2013/06/17/string-concatenation-behind-the-scenes-part-one/ http://ericlippert.com/2013/06/24/string-concatenation-behind-the-scenes-part-two/

like image 163
Stuart Avatar answered Oct 06 '22 19:10

Stuart


I actually built and ran several tests on this. To get to the results of the test, skip to the bottom. I used this benchmarking method:

public static string BenchmarkMethod(Action method, int iterations)
{
    var watch = new Stopwatch();
    var results = new List<TimeSpan>(iterations);
    for (int iteration = 0; iteration < iterations; iteration++)
    {
    watch.Start();
    method();
    watch.Stop();
    results.Add(watch.Elapsed);
    watch.Reset();
    }

    var builder = new StringBuilder();
    builder.Append("Method benchmarked: ");
    builder.Append(method.Method.ReflectedType);
    builder.Append(".");
    builder.AppendLine(method.Method.Name);
    builder.Append("Average time in ticks: ");
    builder.AppendLine(results.Average(t => t.Ticks).ToString());

    return builder.ToString();
}

I wrote several small methods like these:

public static void StringConcatOperatorX8()
{
    var foo = strings[0] + strings[1] + strings[2] + strings[3] + strings[4] + strings[5] + strings[6] + strings[7] + strings[8];
}

and:

public static void StringBuilderAppendsX8()
{
    var builder = new StringBuilder();
    builder.Append(strings[0]);
    builder.Append(strings[1]);
    builder.Append(strings[2]);
    builder.Append(strings[3]);
    builder.Append(strings[4]);
    builder.Append(strings[5]);
    builder.Append(strings[6]);
    builder.Append(strings[7]);
    builder.Append(strings[8]);

    var result = builder.ToString();
}

Where strings is a string array that contains 9, 30 letter strings

They ranged from 1 to 8 concats/appends. I originally wrote them to go from 1 to 6, using 3 letter strings, and took 10,000 samples.

UPDATE: I have been getting far more samples (1 million to be precise) and adding more letters to the strings. Apparently using StringBuilder is a total waste of performance. At 30 letters using the StringBuilder takes twice as long as using the + operator... At the tests taking several seconds now to complete, I think I shall retire from the subject.

FINAL UPDATE: This is very important as well. The difference in using the + operator and the StringBuilder comes in when you concat on different lines. This method actually takes longer than using the StringBuilder:

public static void StringConcatAltOperatorX8()
{
    var foo = strings[0];
    foo += strings[1];
    foo += strings[2];
    foo += strings[3];
    foo += strings[4];
    foo += strings[5];
    foo += strings[6];
    foo += strings[7];
    foo += strings[8];
}

So at 30 letters per string and 1 million samples, combining all strings into a single string in the same call takes about 5.809297 ticks. Combining all strings in separate lines takes about: 12.933227 ticks. Using the StringBuilder takes 11.27558 ticks. My apologies about the length of the reply. It was something that I needed to check into myself.

like image 43
bubbinator Avatar answered Oct 06 '22 18:10

bubbinator