This reply is actually an extended comment (hence wiki) comparing the performance of BitConverter and bitshifting using + vs |; it applies when micro-optimising only!!
Results first:
BitConverter: 972ms, chk=1855032704
Bitwise: 740ms, chk=1855032704
ReadLength: 1316ms, chk=1855032704
Or results if tweaked to allow non-zero base offsets:
BitConverter: 905ms, chk=1855032704
Bitwise: 1058ms, chk=1855032704
ReadLength: 1244ms, chk=1855032704
And the code:
using System;
using System.Diagnostics;
static class Program
{
static void Main()
{
byte[] buffer = BitConverter.GetBytes((uint)123);
const int LOOP = 50000000;
uint chk = 0;
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
chk += BitConverter.ToUInt32(buffer, 0);
}
watch.Stop();
Console.WriteLine("BitConverter: " + watch.ElapsedMilliseconds
+ "ms, chk=" + chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
chk += Bitwise(buffer);
}
watch.Stop();
Console.WriteLine("Bitwise: " + watch.ElapsedMilliseconds
+ "ms, chk=" + chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
chk += ReadLength(buffer);
}
watch.Stop();
Console.WriteLine("ReadLength: " + watch.ElapsedMilliseconds
+ "ms, chk=" + chk);
Console.ReadKey();
}
static uint Bitwise(byte[] buffer)
{
return ((uint)buffer[0])
| (((uint)buffer[1]) << 8)
| (((uint)buffer[2]) << 16)
| (((uint)buffer[3]) << 24);
}
static uint ReadLength(byte[] buffer)
{
uint result = ((uint)buffer[3]) << 24;
result += ((uint)buffer[2]) << 16;
result += ((uint)buffer[1]) << 8;
result += buffer[0];
return result;
}
}