Why is StringBuilder slower when compared to + concatenation?
StringBuilder was meant to avoid extra object creation, but why does it penalize performance?
static void Main(string[] args)
{
int max = 1000000;
for (int times = 0; times < 5; times++)
{
Console.WriteLine("\ntime: {0}", (times+1).ToString());
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < max; i++)
{
string msg = "Your total is ";
msg += "$500 ";
msg += DateTime.Now;
}
sw.Stop();
Console.WriteLine("String +\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
sw = Stopwatch.StartNew();
for (int j = 0; j < max; j++)
{
StringBuilder msg = new StringBuilder();
msg.Append("Your total is ");
msg.Append("$500 ");
msg.Append(DateTime.Now);
}
sw.Stop();
Console.WriteLine("StringBuilder\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
}
Console.Read();
}
EDIT: Moving out of scope variables as suggested:
Change so that the StringBuilder isn't instantiated all the time, instead .Clear() it:
time: 1
String + : 3348ms
StringBuilder : 3151ms
time: 2
String + : 3346ms
StringBuilder : 3050ms
etc.
Note that this still tests exactly the same functionality, but tries to reuse resources a bit smarter.
Code: (also live on http://ideone.com/YuaqY)
using System;
using System.Text;
using System.Diagnostics;
public class Program
{
static void Main(string[] args)
{
int max = 1000000;
for (int times = 0; times < 5; times++)
{
{
Console.WriteLine("\ntime: {0}", (times+1).ToString());
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < max; i++)
{
string msg = "Your total is ";
msg += "$500 ";
msg += DateTime.Now;
}
sw.Stop();
Console.WriteLine("String +\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
}
{
Stopwatch sw = Stopwatch.StartNew();
StringBuilder msg = new StringBuilder();
for (int j = 0; j < max; j++)
{
msg.Clear();
msg.Append("Your total is ");
msg.Append("$500 ");
msg.Append(DateTime.Now);
}
sw.Stop();
Console.WriteLine("StringBuilder\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
}
}
Console.Read();
}
}
You are creating a new instance of StringBuilder with every iteration, and that incurs some overhead. Since you are not using it for what it's actually meant to do (ie: build large strings which would otherwise require many string concatenation operations), it's not surprising to see worse performance than concatenation.
A more common comparison / usage of StringBuilder is something like:
string msg = "";
for (int i = 0; i < max; i++)
{
msg += "Your total is ";
msg += "$500 ";
msg += DateTime.Now;
}
StringBuilder msg_sb = new StringBuilder();
for (int j = 0; j < max; j++)
{
msg_sb.Append("Your total is ");
msg_sb.Append("$500 ");
msg_sb.Append(DateTime.Now);
}
With this, you'll observe a significant performance difference between StringBuilder and concatenation. And by "significant" I mean orders of magnitude, not the ~ 10% difference you are observing in your examples.
Since StringBuilder doesn't have to build tons of intermediary strings that will just get thrown away, you get much better performance. That's what it's meant for. For smaller strings, you are better off using string concatenation for simplicity and clarity.
The benefits of StringBuilder should be noticeable with longer strings.
Every time you concatenate a string you create a new string object, so the longer the string, the more is needed to copy from the old string to the new string.
Also, creating many temporary objects may have an adverse effect on performance that is not measurable by a StopWatch, because it "pollutes" the managed heap with temporary objects and may cause more garbage collection cycles.
Modify your test to create (much) longer strings and use (many) more concatenations / append operations and the StringBuilder should perform better.
Note that
string msg = "Your total is ";
msg += "$500 ";
msg += DateTime.Now;
compiles down to
string msg = String.Concat("Your total is ", "$500 ");
msg = String.Concat(msg, DateTime.Now.ToString());
This totals two concats and one ToString per iteration. Also, a single String.Concat is really fast, because it knows how large the resulting string will be, so it only allocates the resulting string once, and then quickly copies the source strings into it. This means that in practice
String.Concat(x, y);
will always outperform
StringBuilder builder = new StringBuilder();
builder.Append(x);
builder.Append(y);
because StringBuilder cannot take such shortcuts (you could call a thirs Append, or a Remove, that's not possible with String.Concat).
The way a StringBuilder works is by allocating an initial buffer and set the string length to 0. With each Append, it has to check the buffer, possibly allocate more buffer space (usually copying the old buffer to the new buffer), copy the string and increment the string length of the builder. String.Concat does not need to do all this extra work.
So for simple string concatenations, x + y (i.e., String.Concat) will always outperform StringBuilder.
Now, you'll start to get benefits from StringBuilder once you start concatenating lots of strings into a single buffer, or you're doing lots of manipulations on the buffer, where you'd need to keep creating new strings when not using a StringBuilder. This is because StringBuilder only occasionally allocates new memory, in chunks, but String.Concat, String.SubString, etc. (nearly) always allocate new memory. (Something like "".SubString(0,0) or String.Concat("", "") won't allocate memory, but those are degenerate cases.)
In addition to not using StringBuilder as in the most efficient manner, you're also not using string concatenation as efficiently as possible. If you know how many strings you're concatenating ahead of time, then doing it all on one line should be fastest. The compiler optimizes the operation so that no intermediate strings are generated.
I added a couple more test cases. One is basically the same as what sehe suggested, and the other generates the string in one line:
sw = Stopwatch.StartNew();
builder = new StringBuilder();
for (int j = 0; j < max; j++)
{
builder.Clear();
builder.Append("Your total is ");
builder.Append("$500 ");
builder.Append(DateTime.Now);
}
sw.Stop();
Console.WriteLine("StringBuilder (clearing)\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
sw = Stopwatch.StartNew();
for (int i = 0; i < max; i++)
{
msg = "Your total is " + "$500" + DateTime.Now;
}
sw.Stop();
Console.WriteLine("String + (one line)\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
And here is an example of the output I see on my machine:
time: 1
String + : 3707ms
StringBuilder : 3910ms
StringBuilder (clearing) : 3683ms
String + (one line) : 3645ms
time: 2
String + : 3703ms
StringBuilder : 3926ms
StringBuilder (clearing) : 3666ms
String + (one line) : 3625ms
In general:
- StringBuilder does better if you're building a large string in a lot of steps, or you don't know how many strings will be concatenated together.
- Mashing them all together in a single expression is better whenever it's a reasonable option option.
I think its better to compare effeciancy between String and StringBuilder rather then time.
what msdn says:
A String is called immutable because its value cannot be modified once it has been created. Methods that appear to modify a String actually return a new String containing the modification. If it is necessary to modify the actual contents of a string-like object, use the System.Text.StringBuilder class.
string msg = "Your total is "; // a new string object
msg += "$500 "; // a new string object
msg += DateTime.Now; // a new string object
see which one is better.
Here is an example that demonstrates a situation in which StringBuilder will execute more quickly than string concatenation:
static void Main(string[] args)
{
const int sLen = 30, Loops = 10000;
DateTime sTime, eTime;
int i;
string sSource = new String('X', sLen);
string sDest = "";
//
// Time StringBuilder.
//
for (int times = 0; times < 5; times++)
{
sTime = DateTime.Now;
System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1));
Console.WriteLine("Result # " + (times + 1).ToString());
for (i = 0; i < Loops; i++)
{
sb.Append(sSource);
}
sDest = sb.ToString();
eTime = DateTime.Now;
Console.WriteLine("String Builder took :" + (eTime - sTime).TotalSeconds + " seconds.");
//
// Time string concatenation.
//
sTime = DateTime.Now;
for (i = 0; i < Loops; i++)
{
sDest += sSource;
//Console.WriteLine(i);
}
eTime = DateTime.Now;
Console.WriteLine("Concatenation took : " + (eTime - sTime).TotalSeconds + " seconds.");
Console.WriteLine("\n");
}
//
// Make the console window stay open
// so that you can see the results when running from the IDE.
//
}
Result # 1
String Builder took :0 seconds.
Concatenation took : 8.7659616 seconds.
Result # 2
String Builder took :0 seconds.
Concatenation took : 8.7659616 seconds.
Result # 3
String Builder took :0 seconds.
Concatenation took : 8.9378432 seconds.
Result # 4
String Builder took :0 seconds.
Concatenation took : 8.7972128 seconds.
Result # 5
String Builder took :0 seconds.
Concatenation took : 8.8753408 seconds.
StringBulder is much faster than + concatenation..
Related
I'm facing a problem while developing an application.
Basically,
I have a fixed string, let's say "IHaveADream"
I now want to user to insert another string, for my purpose of a fixed length, and then concatenate every character of the fixed string with every character of the string inserted by the user.
e.g.
The user inserts "ByeBye"
then the output would be:
"IBHyaevBeyAeDream".
How to accomplish this?
I have tried with String.Concat and String.Join, inside a for statement, with no luck.
One memory-efficient option is to use a string builder, since both the original string and the user input could potentially be rather large. As mentioned by Kris, you can initialize your StringBuilder capacity to the combined length of both strings.
void Main()
{
var start = "IHaveADream";
var input = "ByeBye";
var sb = new StringBuilder(start.Length + input.Length);
for (int i = 0; i < start.Length; i++)
{
sb.Append(start[i]);
if (input.Length >= i + 1)
sb.Append(input[i]);
}
sb.ToString().Dump();
}
This only safely accounts for the input string being shorter or equal in length to the starting string. If you had a longer input string, you'd want to take the longer length as the end point for your for loop iteration and check that each array index is not out of bounds.
void Main()
{
var start = "IHaveADream";
var input = "ByeByeByeByeBye";
var sb = new StringBuilder(start.Length + input.Length);
var length = start.Length >= input.Length ? start.Length : input.Length;
for (int i = 0; i < length; i++)
{
if (start.Length >= i + 1)
sb.Append(start[i]);
if (input.Length >= i + 1)
sb.Append(input[i]);
}
sb.ToString().Dump();
}
You can create an array of characters and then re-combine them in the order you want.
char[] chars1 = "IHaveADream".ToCharArray();
char[] chars2 = "ByeBye".ToCharArray();
// you can create a custom algorithm to handle
// different size strings.
char[] c = new char[17];
c[0] = chars1[0];
c[1] = chars2[0];
...
c[13] = chars1[10];
string s = new string(c);
var firstString = "Ihaveadream";
var secondString = "ByeBye";
var stringBuilder = new StringBuilder();
for (int i = 0; i< firstString.Length; i++) {
stringBuilder .Append(str[i]);
if (i < secondString.Length) {
stringBuilder .Append(secondStr[i]);
}
}
var result = stringBuilder.ToString();
If you don't care much about memory usage or perfomance you can just use:
public static string concatStrings(string value, string value2)
{
string result = "";
int i = 0;
for (i = 0; i < Math.Max(value.Length, value2.Length) ; i++)
{
if (i < value.Length) result += value[i].ToString();
if (i < value2.Length) result += value2[i].ToString();
}
return result;
}
Usage:
string conststr = "IHaveADream";
string input = "ByeBye";
var result = ConcatStrings(conststr, input);
Console.WriteLine(result);
Output: IBHyaevBeyAeDream
P.S.
Just checked perfomance of both methods (with strBuilder and simple cancatenation) and it appears to be that both of this methods take same time to execute (if you have just one operation). The main reason for it is that string builder take considerable time to initialize while with use of concatenation we don't need that.
But in case if you have to process something like 1500 strings then it's different story and string builder is more of an option.
For 100 000 method executions it showed 85 (str buld) vs 22 (concat) ms respectively.
My Code
Which is more efficient in C#, 1 or 2?
StringBuilder sb = new StringBuilder();
sb.Append("my string " + myVar + " my string"); // 1
sb.AppendFormat("my string {0} my string", myVar); // 2
I'm guessing that the question could also be rephrased:
string y = "my string " + myVar + " my string"; // 1
string x = String.Format("my string {0} my string", myVar); // 2
Version of .NET Framework is important here, because implementation of StringBuilder.Append and StringBuilder.AppendFormat can differ significantly between individual versions. Under .NET Framework 4, (1) is faster than (2), but it is still inefficient because of overhead caused by concatenating (and thus copying) of (sub)strings. This is even 2x faster than (1):
StringBuilder sb = new StringBuilder();
sb.Append("my string");
sb.Append(myVar);
sb.Append(" my string");
UPDATE:
Using following test:
static void Main(string[] args)
{
string myVar = "abcdef";
Stopwatch stopwatch = Stopwatch.StartNew();
for (int j = 0; j < 10000; j++)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
//UNCOMMENT ONE OF THESE TESTS
//Test1
sb.Append("my string " + myVar + " my string");
//Test2
//sb.AppendFormat("my string {0} my string", myVar);
//Test3
//sb.Append("my string ");
//sb.Append(myVar);
//sb.Append(" my string");
}
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds + " ms");
}
I meassured these results on my computer (Intel Core2 Q9400, Windows Server 2008 x64, .NET Framework 4.0, Release mode):
Test1: 10401 ms
Test2: 20262 ms
Test3: 5771 ms
I'm testing the efficiency of an extension method to see which permutation would be the fastest in terms of processing time. Memory consumption isn't an issue at this point..
I've created a small console app to generate an array of of random strings, which then has the extension methods applied to it. I'm currently using the StopWatch class to measure the time taken to run the extension methods. I then average to total time of each method over a number of iterations.
I'm not excluding highest or lowest results at this point.
Extension Methods being tested:
public static String ToString1(this String[] s) {
StringBuilder sb = new StringBuilder();
foreach (String item in s) {
sb.AppendLine(item);
}
return sb.ToString();
}
public static String ToString2(this String[] s) {
return String.Join("\n", s);
}
Program.cs
static void Main(string[] args)
{
long s1Total = 0;
long s2Total = 0;
double s1Avg = 0;
double s2Avg = 0;
int iteration = 1;
int size = 100000;
while (iteration <= 25)
{
Console.WriteLine("Iteration: {0}", iteration);
Test(ref s1Total, ref s2Total, ref iteration, size);
}
s1Avg = s1Total / iteration;
s2Avg = s2Total / iteration;
Console.WriteLine("Version\t\tTotal\t\tAvg");
Console.WriteLine("StringBuilder\t\t{0}\t\t{1}",s1Total, s1Avg);
Console.WriteLine("String.Join:\t\t{0}\t\t{1}",s2Total, s2Avg);
Console.WriteLine("Press any key..");
Console.ReadKey();
}
private static void Test(ref long s1Total, ref long s2Total, ref int iteration, int size)
{
String[] data = new String[size];
Random r = new Random();
for (int i = 0; i < size; i++)
{
data[i] = r.NextString(50);
}
Stopwatch s = new Stopwatch();
s.Start();
data.ToString1();
s.Stop();
s1Total += s.ElapsedTicks;
s.Reset();
s.Start();
data.ToString2();
s.Stop();
s2Total += s.ElapsedTicks;
iteration++;
}
Other extensions methods used in the above code for completeness..
Random extension:
public static String NextString(this Random r,int size)
{
return NextString(r,size,false);
}
public static String NextString(this Random r,int size, bool lowerCase)
{
StringBuilder sb = new StringBuilder();
char c;
for (int i = 0; i < size; i++)
{
c = Convert.ToChar(Convert.ToInt32(Math.Floor(26*r.NextDouble() + 65)));
sb.Append(c);
}
if (lowerCase) {
return sb.ToString().ToLower();
}
return sb.ToString();
}
Running the above code, my results indicate that the StringBuilder based method is faster than String.Join based method.
My Questions:
Is this the right way to be performing this type of measurement..
Is there a better way of doing this?
Are my results in this instance correct, and if so is using a StringBuilder actually faster than String.Join in this situation?
Thanks.
Next time when you want to compare the performance, you can take a look at the source code via reflector. You can easily find that string.Join is using StringBuilder to construct the string. So they have slight performance difference.
I got
StringBuilder 3428567 131867
String.Join: 1245078 47887
Note that ToString1 adds an extra newline.
Also, you can improve it by setting the StringBuilder's capacity.
struct mydata
{
public int id;
public string data;
}
class Program
{
static void Main(string[] args)
{
List<mydata> myc = new List<mydata>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
mydata d = new mydata();
d.id = i;
d.data = string.Format("DataValue {0}",i);
myc.Add(d);
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
}
Whys is this code above so SLOW..?
On an older laptop the times are:
C# code above: 1500ms
Similar code in Delphi: 450ms....
I then changed the code to a KeyValue/Pair (see below):
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var list = new List<KeyValuePair<int , string>>();
for (int i = 0; i < 1000000; i++)
{
list.Add(new KeyValuePair<int,string>(i, "DataValue" + i));
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
This improved the time to 1150ms..
If I remove the '+ i' the time is < 300ms
If I try and replace it with a StringBuilder, the timing is similar.
StringBuilder sb = new StringBuilder();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var list = new List<KeyValuePair<int, string>>();
for (int i = 0; i < 1000000; i++)
{
sb.Append("DataValue");
sb.Append(i);
list.Add(new KeyValuePair<int, string>(i, sb.ToString()));
sb.Clear();
}
stopWatch.Stop();
Console.WriteLine("End: {0}", stopWatch.ElapsedMilliseconds);
Console.ReadLine();
Is slightly better.. If you remove the sb.Append(i) its very fast..
It would appear that any time you have to add an Int to a string/stringbuilder its VERY SLOW..
Can I speed this up in any way ??
EDIT **
The code below is the quickest I can get after making suggestions:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication1
{
struct mydata
{
public int id;
public string data;
}
class Program
{
static void Main(string[] args)
{
List<mydata> myc = new List<mydata>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
mydata d = new mydata();
d.id = i;
d.data = "DataValue " + i.ToString();
myc.Add(d);
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
}
}
If I replace the line:
d.data = "DataValue " + i.ToString();
with:
d.data = "DataValue ";
On my home machine this goes from 660ms -> 31ms..
Yes.. its 630ms slower with the '+ i.ToString()'
But still 2x faster than boxing/string.format etc etc..
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var list = new List<KeyValuePair<int, string>>();
for (int i = 0; i < 1000000; i++)
{
list.Add(new KeyValuePair<int, string>(i, "DataValue" +i.ToString()));
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
is 612ms.. (no difference in speed if List>(1000000); is pre-initialised).
The problem with your first two examples is that the integer must first be boxed and then converted to a string. The boxing causes the code to be slower.
For example, in this line:
d.data = string.Format("DataValue {0}", i);
the second parameter to string.Format is object, which causes boxing of i. See the intermediate language code for confirmation of this:
...
box int32
call string [mscorlib]System.String::Format(string, object)
...
Similarly this code:
d.data = "DataValue " + i;
is equivalent to this:
d.data = String.Concat("DataValue ", i);
This uses the overload of String.Concat with parameters of type object so again this involves a boxing operation. This can be seen in the generated intermediate language code:
...
box int32
call string [mscorlib]System.String::Concat(object, object)
...
For better performance this approach avoids the boxing:
d.data = "DataValue " + i.ToString();
Now the intermediate language code doesn't include the box instruction and it uses the overload of String.Concat that takes two strings:
...
call instance string [mscorlib]System.Int32::ToString()
call string [mscorlib]System.String::Concat(string, string)
...
On my machine:
... String.Format("DataValue {0}", i ) // ~1650ms
... String.Format("DataValue {0}", "") // ~1250ms
... new MyData {Id = i, Data = "DataValue {0}" + i} // ~1200ms
As Mark said, there's a boxing operation involved.
For this specific case, when you get your DataValue based on your id, you could to create a get property or to override ToString() method to do that operation just when you need it.
public override string ToString()
{
return "DataValue {0}" + Id;
}
There are a lot of things wrong with the above which will be affecting your results.
First, none of the comparisons you've done are equal. In both you have a list, and use Add, what you add to the list won't affect the time, changing the declaration of the List to var won't affect the time.
I'm not convinced by the boxing argument put up by Mark, this can be a problem, but I'm pretty certain in the first case there is an implicit call to .ToString. This has its own overhead, and would be needed even if the int is boxed.
Format is quite an expensive operation.
The second version has a string concatenation which is probably cheaper than a .Format.
The third is just expensive all the way. Using a string builder like that is not efficient. Internally a stringbuilder is just a list. When you do a .ToString on it you essentially do a big concat operation then.
The reason some of the operations might suddenly run really quickly if you take out a critical line is that the compile can optimise out bits of code. If it seems to be doing the same thing over and over it might not do it (Gross over simplification).
Right, so here's my suggestion:
The first version is probably the nearest to being "right" in my mind. What you could do is defer some of the processing. Take the object mydata and set a string property AND an int property. Then only when you need to do the read of the string produce the output via a concat. Save that if you're going to repeat the print operation a lot. It won't necessarilly be quicker in the way you expect.
Another major performance killer in this code is the List. Internally it stores the items in an array. When you call Add, it checks if the new Item can fit into the array (EnsureCapacitiy). When it needs more room, it will create a NEW array with double the size, and then COPY the items from the old array into the new one. You can see all this going on if you check out List.Add in Reflector.
So in your code with 1,000,000 items, it needs to copy the array some 25 times, and they're bigger each time.
If your change your code to
var list = new List<KeyValuePair<int, string>>(1000000);
you should see a dramatic increase in speed. Let us know how you fare!
Regards,
GJ
I'm getting a "FormatException: Input string was not in a correct format" error that I don't understand.
I'm using the following lines to write a string to a text file:
using (StreamWriter sw = new StreamWriter(myfilename, false, System.Text.Encoding.GetEncoding(enc)))
{
sw.Write(mystring, Environment.NewLine);
}
(the encoding part is because I do have an option in my application to set it to utf-8 or iso-8859-1... but I think that's irrelevant).
All of my strings write out just fine except this one string that is different from the others because it actually has a snippet of javascript code in it. I'm sure that one of the special characters there might be causing the problem but how do I know?
The one thing I tried was to insert the following line just before the sw.Write statement above:
System.Console.WriteLine(mystring);
and it wrote out to the console just fine - no error.
Help?
Thanks! (and Happy New Year!)
-Adeena
The overload you are using takes the format as the first parameter, and objects to inject after that.
You can do either of the following:
sw.Write(mystring + Environment.NewLine);
or
sw.Write("{0}{1}", mystring, Environment.NewLine);
In response to the comments from DK, I tested to what extend string concatenation is slower. I made this setup with three options;
concatenating the string
calling sw.Write twice
calling sw.WriteLine
On my machine, the second option is about 88% faster than average. At 10000000 iterations they use 3517, 2420 and 3385 milliseconds.
It should only be significant if this is code that is called many times in your program.
using System;
using System.IO;
using System.Text;
class Program
{
static void Main(string[] args)
{
const string myString = "kdhlkhldhcĂžehdhkjehdkhekdhk";
int iterations=getIntFromParams(args, 0, 10);
int method = getIntFromParams(args, 1, 0);
var fileName=Path.GetTempFileName();
using (StreamWriter sw = new StreamWriter(fileName, false, Encoding.Default))
{
switch (method)
{
case 0:
Console.WriteLine("Starting method with concatenation. Iterations: " + iterations);
var start0 = DateTimeOffset.Now;
for (int i = 0; i < iterations; i++)
{
sw.Write(myString + Environment.NewLine);
}
var time0 = DateTimeOffset.Now - start0;
Console.WriteLine("End at " + time0.TotalMilliseconds + " ms.");
break;
case 1:
Console.WriteLine("Starting method without concatenation. Iterations: " + iterations);
var start1 = DateTimeOffset.Now;
for (int i = 0; i < iterations; i++)
{
sw.Write(myString);
sw.Write(Environment.NewLine);
}
var time1 = DateTimeOffset.Now - start1;
Console.WriteLine("End at " + time1.TotalMilliseconds + " ms.");
break;
case 2:
Console.WriteLine("Starting method without concatenation, using WriteLine. Iterations: " + iterations);
var start2 = DateTimeOffset.Now;
for (int i = 0; i < iterations; i++)
{
sw.WriteLine(myString);
}
var time2 = DateTimeOffset.Now - start2;
Console.WriteLine("End at " + time2.TotalMilliseconds + " ms.");
break;
}
}
}
private static int getIntFromParams(string[] args, int index, int #default)
{
int value;
try
{
if (!int.TryParse(args[index], out value))
{
value = #default;
}
}
catch(IndexOutOfRangeException)
{
value = #default;
}
return value;
}
}