Comparer deux tableaux d'octets en .NET

Comparer deux tableaux d’octets en .NET

Edit : la methode rapide moderne consiste a utiliser a1.AsSpan().SequenceEquals(a2)

L’utilisateur gil a suggere du code unsafe qui a inspire cette 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) {
  unchecked {
    if(a1==a2) return true;
    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;
    }
  }
}

ce qui effectue une comparaison basee sur 64 bits pour autant du tableau que possible. Cela repose en quelque sorte sur le fait que les tableaux commencent alignes sur un qword. Cela fonctionnera s’ils ne sont pas alignes sur un qword, mais pas aussi rapidement que s’ils l’etaient.

Cette methode est environ sept fois plus rapide que la simple boucle for. L’utilisation de la bibliotheque J# a donne des performances equivalentes a la boucle for originale. L’utilisation de .SequenceEqual est environ sept fois plus lente ; nous pensons que c’est simplement parce qu’il utilise IEnumerator.MoveNext. Nous imaginons que les solutions basees sur LINQ sont au moins aussi lentes, voire pires.