没有绑定检查的C#byte 比较

我正在寻找性能有效的方法来比较两个字节[]的相等性。 大小超过1 MB,因此应尽量减少每个数组元素的开销。

我的目标是通过避免对两个数组的重复绑定检查来击败SequenceEqual或每个项目上的手动编码for循环的速度。 就像Array.Copy可以导致快速memcpy ,什么会导致memcmp

如果性能真的很重要,那么最快的方法是使用每个版本的Windows附带的CRT库。 这个代码在我的poky笔记本电脑上需要大约51毫秒,也适用于64位机器:

 using System; using System.Runtime.InteropServices; using System.Diagnostics; class Program { static void Main(string[] args) { byte[] arr1 = new byte[50 * 1024 * 1024]; byte[] arr2 = new byte[50 * 1024 * 1024]; var sw = Stopwatch.StartNew(); bool equal = memcmp(arr1, arr2, arr1.Length) == 0; sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadLine(); } [DllImport("msvcrt.dll")] private static extern int memcmp(byte[] arr1, byte[] arr2, int cnt); } 

您可以使用不安全的代码来执行指针操作。 您可以将四个字节一次比较为整数:

 public static bool ArrayCompare(byte[] a, byte[] b) { if (a.Length != b.Length) return false; int len = a.Length; unsafe { fixed(byte* ap = a, bp = b) { int* aip = (int*)ap, bip = (int*)bp; for (;len >= 4;len-=4) { if (*aip != *bip) return false; aip++; bip++; } byte* ap2 = (byte*)aip, bp2 = (byte*)bip; for (;len>0;len--) { if (*ap2 != *bp2) return false; ap2++; bp2++; } } } return true; } 

对一个简单的循环进行了测试,它的速度提高了大约六倍。

正如Josh Einstein所建议的那样,long可用于64位系统。 实际上它在32位和64位系统上似乎几乎快了两倍:

 public static bool ArrayCompare64(byte[] a, byte[] b) { if (a.Length != b.Length) return false; int len = a.Length; unsafe { fixed (byte* ap = a, bp = b) { long* alp = (long*)ap, blp = (long*)bp; for (; len >= 8; len -= 8) { if (*alp != *blp) return false; alp++; blp++; } byte* ap2 = (byte*)alp, bp2 = (byte*)blp; for (; len > 0; len--) { if (*ap2 != *bp2) return false; ap2++; bp2++; } } } return true; } 

来自: http ://www.pinvoke.net/default.aspx/msvcrt.memcmp:memcmp的下述签名(由Saar提供)仅为x64签名。 在x86计算机上仅使用x64签名将导致PInvoke堆栈不平衡。 对于x86和x64平台兼容性,请确保使用指定Cdecl调用约定的签名,并使用UIntPtr类型正确编组size_t count参数:

  [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] static extern int memcmp(byte[] b1, byte[] b2, UIntPtr count); static bool doImagesMatch(byte[] b1, byte[] b2) { return b1.Length == b2.Length && memcmp(b1, b2, new UIntPtr((uint)b1.Length)) == 0; } 

我成功地使用了这段代码,但我还没来得及衡量性能。 我正在使用大约600字节的小数组。 我必须使用与x86兼容的代码,因为我们的非营利组织中的绝大多数计算机都是x86。

显然你需要一个快速的algorhythm来将位图转换为byte []。

[DllImport(“msvcrt.dll”)] unsafe static extern int memcmp(void * b1,void * b2,long count);

  unsafe static int ByteArrayCompare1(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length) { CompareCount++; fixed (byte* p1 = b1) fixed (byte* p2 = b2) { int cmp = memcmp(p1 + b1Index, p2 + b2Index, Math.Min(b1Length, b2Length)); if (cmp == 0) { cmp = b1Length.CompareTo(b2Length); } return cmp; } }