Я ищу производительность эффективные способы сравнить два байта [] для равенства. Размеры выше 1 МБ, таким образом, издержки для каждого элемента массива должны быть минимизированы.
Я стремлюсь побеждать скорости SequenceEqual
или кодированный рукой для цикла по каждому объекту, путем предотвращения повторяющихся проверок принадлежности к диапазону на оба массива. Таким же образом это Array.Copy
мог привести к быстро memcpy
, что приведет к a memcmp
?
Если производительность действительно имеет значение, то самый быстрый способ сделать это, используя библиотеку CRT, включенной с каждой версией Windows. Этот код занимает ~ 51 мсек на моем ноутбуке Poky, работает на 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;
}
A проверили это на простом цикле, и это примерно в шесть раз быстрее.
Как предложил Джош Эйнштейн, 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;
}