Skip to content

Instantly share code, notes, and snippets.

@keimpema
Last active June 7, 2017 15:15
Show Gist options
  • Save keimpema/3804744f81c5b7423ad88a22361338a4 to your computer and use it in GitHub Desktop.
Save keimpema/3804744f81c5b7423ad88a22361338a4 to your computer and use it in GitHub Desktop.
Compare Linq, For and ForEach loops for calculating crc32 hash value.
using System.Linq;
namespace ConsoleApp1
{
public static class Crc32
{
private const uint polynomial = 0xEDB88320;
private const uint seed = 0xFFFFFFFF;
private static readonly uint[] lookupTable;
static Crc32()
{
lookupTable = CreateLookupTable();
}
public static uint CalculateChecksumWithLinq(byte[] buffer)
{
return buffer.Aggregate(seed,
(value, b) => (value >> 8) ^ lookupTable[(value & 0xFF) ^ b],
value => value ^ seed);
}
public static uint CalculateChecksumForEach(byte[] buffer)
{
uint value = seed;
foreach (byte b in buffer)
{
value = (value >> 8) ^ lookupTable[(value & 0xFF) ^ b];
}
return value ^ seed;
}
public static uint CalculateChecksumFor(byte[] buffer)
{
uint value = seed;
for (var i = 0; i < buffer.Length; i++)
{
value = (value >> 8) ^ lookupTable[(value & 0xFF) ^ buffer[i]];
}
return value ^ seed;
}
public static uint CalculateChecksum(byte[] buffer)
{
return CalculateChecksumForEach(buffer);
}
private static uint[] CreateLookupTable()
{
var table = new uint[256];
for (uint i = 0; i < 256; i++)
{
uint entry = i;
for (var j = 0; j < 8; j++)
{
entry = (entry & 1) == 1 ? (entry >> 1) ^ polynomial : entry >> 1;
}
table[i] = entry;
}
return table;
}
}
internal class Program
{
private static void Main(string[] args)
{
const int loopCount = 1;
const int dataCount = 100000000;
var rnd = new Random((int)DateTime.Now.Ticks);
var data = new byte[dataCount];
rnd.NextBytes(data);
// for
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < loopCount; i++)
{
Crc32.CalculateChecksumFor(data);
}
sw.Stop();
long durationFor = sw.ElapsedMilliseconds;
// foreach
sw.Reset();
sw.Start();
for (var i = 0; i < loopCount; i++)
{
Crc32.CalculateChecksumForEach(data);
}
sw.Stop();
long durationForEach = sw.ElapsedMilliseconds;
// linq
sw.Reset();
sw.Start();
for (var i = 0; i < loopCount; i++)
{
Crc32.CalculateChecksumWithLinq(data);
}
sw.Stop();
long durationLinq = sw.ElapsedMilliseconds;
Console.WriteLine($"DurationFor = {durationFor}");
Console.WriteLine($"DurationForEach = {durationForEach}");
Console.WriteLine($"DurationLinq = {durationLinq}");
Console.ReadLine();
}
}
}
@keimpema
Copy link
Author

keimpema commented Jun 7, 2017

Output on my machine:

DurationFor = 252
DurationForEach = 252
DurationLinq = 854

The For and ForEach methods are not always the same but they are always close. The Linq method is considerably slower.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment