Expanding on C.Evenhuis's answer, here's some variations that should be quite a bit faster. I'm unsure though of their correctness, anybody with more bit-fiddling experience wanna help me out? I know they don't give the same checksum as the per-byte one, but I do think they give a checksum that's as good (not very, but apparently sufficient) as the per-byte one.
As I said in the comment, you could improve the speed a lot by not comparing byte-per-byte, but treating the array as a 4 times smaller array of ints, or an 8 times smaller array of longs. Treating it as a long[]
only provides a performance benefit on 64-bit though.
static unsafe uint ChecksumInt(byte[] array)
{
unchecked
{
uint checksum = 0;
fixed (byte* ptr = array)
{
var intPtr = (uint*)ptr;
var iterations = array.Length / 4;
var remainderIterations = array.Length % 4;
for (var i = 0; i < iterations; i++)
{
var val = intPtr[i];
checksum += val;
}
while (remainderIterations >= 0) // no more than 3 iterations
{
checksum += ptr[array.Length - remainderIterations];
remainderIterations--;
}
return checksum;
}
}
}
static unsafe ulong ChecksumLong(byte[] array)
{
unchecked
{
ulong checksum = 0;
fixed (byte* ptr = array)
{
var intPtr = (ulong*)ptr;
var iterations = array.Length / 8;
var remainderIterations = array.Length % 8;
for (var i = 0; i < iterations; i++)
{
var val = intPtr[i];
checksum += val;
}
while (remainderIterations >= 0) // no more than 7 iterations
{
checksum += ptr[array.Length - remainderIterations];
remainderIterations--;
}
return checksum;
}
}
}
My performance measurements on 64-bit (Core 2 Duo 3 GHz) for an array of 100,000 items over 10,000 iterations:
- Per 1 byte: 00:00:00.7052533
- Per 4 bytes: 00:00:00.1761491
- Per 8 bytes: 00:00:00.0856880
So quite a bit faster.
But, like I said, I don't know for sure if this provides an equally good checksum.