Last active
June 7, 2017 15:15
-
-
Save keimpema/3804744f81c5b7423ad88a22361338a4 to your computer and use it in GitHub Desktop.
Compare Linq, For and ForEach loops for calculating crc32 hash value.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.