(background: Why should I use int instead of a byte or short in C#)
To satisfy my own curiosity about the pros and cons of using the "appropriate size" integer vs the "optimized" integer i wrote the following code which reinforced what I previously held true about int performance in .Net (and which is explained in the link above) which is that it is optimized for int performance rather than short or byte.
DateTime t;
long a, b, c;
t = DateTime.Now;
for (int index = 0; index < 127; index++)
{
Console.WriteLine(index.ToString());
}
a = DateTime.Now.Ticks - t.Ticks;
t = DateTime.Now;
for (short index = 0; index < 127; index++)
{
Console.WriteLine(index.ToString());
}
b=DateTime.Now.Ticks - t.Ticks;
t = DateTime.Now;
for (byte index = 0; index < 127; index++)
{
Console.WriteLine(index.ToString());
}
c=DateTime.Now.Ticks - t.Ticks;
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.WriteLine(c.ToString());
This gives roughly consistent results in the area of…
~950000
~2000000
~1700000
Which is in line with what i would expect to see.
However when I try repeating the loops for each data type like this…
t = DateTime.Now;
for (int index = 0; index < 127; index++)
{
Console.WriteLine(index.ToString());
}
for (int index = 0; index < 127; index++)
{
Console.WriteLine(index.ToString());
}
for (int index = 0; index < 127; index++)
{
Console.WriteLine(index.ToString());
}
a = DateTime.Now.Ticks - t.Ticks;
The numbers are more like…
~4500000
~3100000
~300000
Which I find puzzling. Can anyone offer an explanation?
NOTE:
In the interest of comparing like for like i’ve limited the loops to 127 because of the range of the byte value type.
Also this is an act of curiosity not production code micro-optimization.
First of all, it’s not .NET that’s optimized for
intperformance, it’s the machine that’s optimized because 32 bits is the native word size (unless you’re on x64, in which case it’slongor 64 bits).Second, you’re writing to the console inside each loop – that’s going too be far more expensive than incrementing and testing the loop counter, so you’re not measuring anything realistic here.
Third, a
bytehas range up to 255, so you can loop 254 times (if you try to do 255 it will overflow and the loop will never end – but you don’t need to stop at 128).Fourth, you’re not doing anywhere near enough iterations to profile. Iterating a tight loop 128 or even 254 times is meaningless. What you should be doing is putting the
byte/short/intloop inside another loop that iterates a much larger number of times, say 10 million, and check the results of that.Finally, using
DateTime.Nowwithin calculations is going to result in some timing “noise” while profiling. It’s recommended (and easier) to use the Stopwatch class instead.Bottom line, this needs many changes before it can be a valid perf test.
Here’s what I’d consider to be a more accurate test program:
This runs each loop inside a much larger loop (5 million iterations) and performs a very simple operation inside the loop (increments a variable). The results for me were:
So, no appreciable difference.
Also, make sure you profile in release mode, a lot of people forget and test in debug mode, which will be significantly less accurate.