在.NET中比较两个字节数组数组、字节、两个、NET

2023-09-02 20:41:52 作者:旧岛听风

我怎样才能做到这一点快?

How can I do this fast?

相信我能做到这一点:

static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
    if (a1.Length != a2.Length)
        return false;

    for (int i=0; i<a1.Length; i++)
        if (a1[i]!=a2[i])
            return false;

    return true;
}

但我在寻找任何一个 BCL 功能和某些高度优化的行之有效的方法来做到这一点。

But I'm looking for either a BCL function or some highly optimized proven way to do this.

java.util.Arrays.equals((sbyte[])(Array)a1, (sbyte[])(Array)a2);

工作得很好,但它并不像她那样将工作64。

works nicely, but it doesn't look like that would work for x64.

请注意我的超快响应这里。

推荐答案

用户的吉的建议不安全code这催生了该解决方案:

User gil suggested unsafe code which spawned this solution:

// Copyright (c) 2008-2013 Hafthor Stefansson
// Distributed under the MIT/X11 software license
// Ref: http://www.opensource.org/licenses/mit-license.php.
static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) {
  if(a1==null || a2==null || a1.Length!=a2.Length)
    return false;
  fixed (byte* p1=a1, p2=a2) {
    byte* x1=p1, x2=p2;
    int l = a1.Length;
    for (int i=0; i < l/8; i++, x1+=8, x2+=8)
      if (*((long*)x1) != *((long*)x2)) return false;
    if ((l & 4)!=0) { if (*((int*)x1)!=*((int*)x2)) return false; x1+=4; x2+=4; }
    if ((l & 2)!=0) { if (*((short*)x1)!=*((short*)x2)) return false; x1+=2; x2+=2; }
    if ((l & 1)!=0) if (*((byte*)x1) != *((byte*)x2)) return false;
    return true;
  }
}

该做的64位基于比较之多阵列成为可能。这种计数的一个事实,即阵列开始qword的对准。它会工作,如果不是四字排列,只是没有那么快,就好像它是。

which does 64-bit based comparison for as much of the array as possible. This kind of counts on the fact that the arrays start qword aligned. It'll work if not qword aligned, just not as fast as if it were.

据执行约七计时器比简单的循环更快。使用J#库执行等效于原来的循环。使用.SequenceEqual运行周围七次慢;我觉得只是因为它是用IEnumerator.MoveNext。我想LINQ为基础的解决方案是至少慢或更坏。

It performs about seven timers faster than the simple for loop. Using the J# library performed equivalently to the original for loop. Using .SequenceEqual runs around seven times slower; I think just because it is using IEnumerator.MoveNext. I imagine LINQ-based solutions being at least that slow or worse.