I have put together some revised code, as well as implemented a better mechanism for benchmarking code execution performance using the diagnostics stopwatch.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace GenericsPerformance
{
class Program
{
static void Main(string[] args)
{
int intVal = 0;
string strVal = "";
//Generics Test-------------------------------------------------------
System.Diagnostics.Stopwatch genericSW = new System.Diagnostics.Stopwatch();
genericSW.Start();
Stack<int> genStack = new Stack<int>();
for (int i = 0; i < 1000000; i++)
genStack.Push(i);
for (int i = 0; i < 1000000; i++)
intVal = genStack.Pop();
genericSW.Stop();
Console.WriteLine("Generics (using int): {0} ms", genericSW.ElapsedMilliseconds);
//--------------------------------------------------------------------
//Non-generics Test---------------------------------------------------
System.Diagnostics.Stopwatch nongenericSW = new System.Diagnostics.Stopwatch();
nongenericSW.Start();
Stack nonGenStack = new Stack();
for (int i = 0; i < 1000000; i++)
nonGenStack.Push(i);
for (int i = 0; i < 1000000; i++)
intVal = (int)nonGenStack.Pop();
nongenericSW.Stop();
Console.WriteLine("Non-Generics (using int): {0} ms", nongenericSW.ElapsedMilliseconds);
//--------------------------------------------------------------------
//Generics Test-------------------------------------------------------
System.Diagnostics.Stopwatch genericSW2 = new System.Diagnostics.Stopwatch();
genericSW2.Start();
Stack<string> genStack2 = new Stack<string>();
for (int i = 0; i < 1000000; i++)
genStack2.Push(i.ToString());
for (int i = 0; i < 1000000; i++)
strVal = genStack2.Pop();
genericSW2.Stop();
Console.WriteLine("Generics (using string): {0} ms", genericSW2.ElapsedMilliseconds);
//--------------------------------------------------------------------
//Non-generics Test---------------------------------------------------
System.Diagnostics.Stopwatch nongenericSW2 = new System.Diagnostics.Stopwatch();
nongenericSW2.Start();
Stack nonGenStack2 = new Stack();
for (int i = 0; i < 1000000; i++)
nonGenStack2.Push(i.ToString());
for (int i = 0; i < 1000000; i++)
strVal = (string)nonGenStack2.Pop();
nongenericSW2.Stop();
Console.WriteLine("Non-Generics (using string): {0} ms", nongenericSW2.ElapsedMilliseconds);
//--------------------------------------------------------------------
Console.ReadLine();
}
}
}
While the results varied slightly each run, I will show you 3 separate runs of this program. You'll notice that I first show Generics vs. Non-generics using a value type of int (this SHOULD perform better). I then show Generics vs. Non-generics using a reference type of string (Microsoft makes no claim on performance gain in this instance).Run 1 Result:
Generics (using int): 49 ms
Non-Generics (using int): 212 ms
Generics (using string): 911 ms
Non-Generics (using string): 912 ms
Run 2 Result:
Generics (using int): 50 ms
Non-Generics (using int): 230 ms
Generics (using string): 935 ms
Non-Generics (using string): 944 ms
Run 3 Result:
Generics (using int): 50 ms
Non-Generics (using int): 212 ms
Generics (using string): 899 ms
Non-Generics (using string): 908 ms
As can be seen, generics using appropriate value types (such as int) show a dramatically improved performance gain, whereas generics using reference types (such as string) only perform slightly better than their non-generic counterpart.
8 comments:
I received slower times for Generic using strings than non-generics.
That doesn't surprise me. Results will definitely vary when using strings with generics (or any reference type for that matter).
Try revising the test program so that all of the strings are built first. Then you are not timing calls to i.ToString(). My machine will give results along the lines of Build test strings : 1252 ms
Generics (using string): 147 ms
Non-Generics (using string): 209 ms
if I build a string[] first.
string is not a value type, this does not apply. although string is a native type it is still a reference type, the value type is a char array.
Your tests are wrong. Generics are much slower at operations then non generic methods or operations
Incorrect. This post confirms what Microsoft conveys, and that is that generics provide a slight performance edge since they do not require boxing/unboxing nor typecasting of the values.
And to the other Anonymous who felt compelled to repeat what is in my blog post, I explicitly stated that "string" is a reference type and that MS made no statements regarding performance gains for reference types. The "string" type was merely added to the test for information, not confirmation of performance.
I've found that C# generic arrays are actually far faster than STL vectors in C++ and are not far behind the performance of native code arrays. Check this out:
http://www.treatyist.com/issue1/cpp_vs_csharp_arrays.aspx
Post a Comment