比较2个相同长度的byteArrays

时间:2012-08-31 23:18:05

标签: c# performance bytearray

我正在研究@stackOverFlow的两种方法,我想可能会有更多的方法 在其他地方,我的问题是最好的表现是什么

和第二个问题,我的代码只需要几个byte[]

     bool ArraysEqual(byte[] a1, byte[] a2)
     {
         if (a1 == a2)
             return true;
          if (a1 == null || a2 == null)
             return false;
          if (a1.Length != a2.Length)
             return false;
          for (int i = 0; i < a1.Length; i++)
         {
             if (a1[i] != a2[i])
                 return false;
         }
         return true;
     } 

并且我无法实现这一点,而不是使用错误的语法来解决workaroud iguess 所以,如果我有一个帮助方法来读取byet []文件

    public byte[] readByteArr(string FilePath)
    {
       return File.ReadAllBytes(FilePath);

    } 

i could make it simply via 



void CompareIt(){

byte[] src = readByteArr(S.bar);
byte[] dest = readByteArr(D.bar);
if(ArraysEqual(src, dest))
DoSomthing
}

我如何制作CompareIt(),在第二个代码中需要参数组,我也试图实现,只是为了检查哪个执行beeter

    bool ArraysEqual<T>(T[] a1, T[] a2)
    {
     if (ReferenceEquals(a1,a2))
         return true;
      if (a1 == null || a2 == null)
         return false;
      if (a1.Length != a2.Length)
         return false;
      EqualityComparer<T> comparer = EqualityComparer<T>.Default;
     for (int i = 0; i < a1.Length; i++)
     {
         if (!comparer.Equals(a1[i], a2[i]))
            return false;
     }
     return true;
 } 

实现最后一个的正确语法是什么,如果有更快的方法来比较两个

 byte[] 

知道他们的长度相同。 你觉得这个怎么样?

重新编辑: enter image description here

第一个是不安全的代码。

第二个是我写的第一个代码(bool ArraysEqual()

,第三是

myArray.SequenceEqual(otherArray); 

现在好好看看这个 请允许我宣布,获胜者是:

[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int memcmp(byte[] b1, byte[] b2, long count);

static bool ByteArrayCompare(byte[] b1, byte[] b2)
{
    // Validate buffers are the same length.     
    // This also ensures that the count does not exceed the length of either buffer.
    return b1.Length == b2.Length && memcmp(b1, b2, b1.Length) == 0;
}

@Chaos。 你可以用我的Pinvoke 发布你的Random的实现吗?

enter image description here

2 个答案:

答案 0 :(得分:4)

如果您使用.NET&gt; 3.0:

myArray.SequenceEqual(otherArray);

请参阅MSDN - Enumerable.SequenceEqual

如果您想使用自定义“EqualityComparer”,可以使用MSDN - Enumerable.SequenceEqual with IEqualityComparer

- )

答案 1 :(得分:1)

  • 最佳:数据是随机的
  • 最差:数据相等
  • 平均值:最佳案例和最差案例的平均值

真正的测试将包括数据几乎相等的情况,但我们在这里看到的平均值让我们非常清楚如果您的数据几乎可以是任何东西,这些事情将如何执行。最好的算法实际上是您期望的数据类型。请注意,单线程安全方法在最好的情况下是最快的,但在最坏的情况下是最慢的。

Performance

class Program
{
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int memcmp(byte[] b1, byte[] b2, long count);

    static bool AreEqualNative(byte[] a, byte[] b)
    {
        if (a == b)
            return true;
        if (a == null || b == null)
            return false;
        if (a.Length != b.Length)
            return false;
        return memcmp(a, b, a.Length) == 0;
    }

    static bool AreEqualSafe(byte[] a1, byte[] a2)
    {
        if (a1 == a2)
            return true;
        if (a1 == null || a2 == null)
            return false;
        if (a1.Length != a2.Length)
            return false;
        for (int i = 0; i < a1.Length; i++)
        {
            if (a1[i] != a2[i])
                return false;
        }
        return true;
    }

    static bool AreEqualSafeParallel(byte[] a1, byte[] a2, int start, int length)
    {
        for (int i = start; i < length; i++)
        {
            if (a1[i] != a2[i])
                return false;
        }
        return true;
    }

    static bool AreEqualSafeParallel(byte[] a, byte[] b)
    {
        if (a == b)
            return true;
        if (a == null || b == null)
            return false;
        if (a.Length != b.Length)
            return false;
        bool b1 = false;
        bool b2 = false;
        bool b3 = false;
        bool b4 = false;
        int quar = a.Length / 4;
        Parallel.Invoke(
            () => b1 = AreEqualSafeParallel(a, b, 0, quar),
            () => b2 = AreEqualSafeParallel(a, b, quar, quar),
            () => b3 = AreEqualSafeParallel(a, b, quar * 2, quar),
            () => b4 = AreEqualSafeParallel(a, b, quar * 3, a.Length)
        );
        return b1 && b2 && b3 && b4;
    }

    static unsafe bool AreEqualUnsafe(byte[] a, byte[] b)
    {
        if (a == b)
            return true;
        if (a == null || b == null)
            return false;
        if (a.Length != b.Length)
            return false;
        int len = a.Length / 8;
        if (len > 0)
        {
            fixed (byte* ap = &a[0])
            fixed (byte* bp = &b[0])
            {
                long* apl = (long*)ap;
                long* bpl = (long*)bp;

                for (int i = 0; i < len; i++)
                {
                    if (apl[i] != bpl[i])
                        return false;
                }
            }
        }
        int rem = a.Length % 8;
        if (rem > 0)
        {
            for (int i = a.Length - rem; i < a.Length; i++)
            {
                if (a[i] != b[i])
                    return false;
            }
        }
        return true;
    }

    static unsafe bool AreEqualUnsafeParallel(byte[] a, byte[] b, int start, int length)
    {
        int len = length / 8;
        if (len > 0)
        {
            fixed (byte* ap = &a[0])
            fixed (byte* bp = &b[0])
            {
                long* apl = (long*)ap;
                long* bpl = (long*)bp;

                for (int i = start; i < len; i++)
                {
                    if (apl[i] != bpl[i])
                        return false;
                }
            }
        }
        int rem = length % 8;
        if (rem > 0)
        {
            for (int i = length - rem; i < length; i++)
            {
                if (a[i] != b[i])
                    return false;
            }
        }
        return true;
    }

    static unsafe bool AreEqualUnsafeParallel(byte[] a, byte[] b)
    {
        if (a == b)
            return true;
        if (a == null || b == null)
            return false;
        if (a.Length != b.Length)
            return false;
        bool b1 = false;
        bool b2 = false;
        bool b3 = false;
        bool b4 = false;
        int quar = a.Length / 4;
        Parallel.Invoke(
            () => b1 = AreEqualUnsafeParallel(a, b, 0, quar),
            () => b2 = AreEqualUnsafeParallel(a, b, quar, quar),
            () => b3 = AreEqualUnsafeParallel(a, b, quar * 2, quar),
            () => b4 = AreEqualUnsafeParallel(a, b, quar * 3, a.Length)
        );
        return b1 && b2 && b3 && b4;
    }

    static readonly Random _rnd = new Random();
    static void SpeedTest(string name, int length, int iterations, Func<byte[], byte[], bool> func)
    {
        var a = new byte[length];
        var b = new byte[length];

        _rnd.NextBytes(a);
        _rnd.NextBytes(b);

        var sw1 = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            func(a, b);
        }
        sw1.Stop();

        var c = new byte[length];
        var d = new byte[length];

        var sw2 = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            func(c, d);
        }
        sw2.Stop();

        Console.WriteLine(name + ":");
        Console.WriteLine("  Best: " + sw1.Elapsed);
        Console.WriteLine("  Worst: " + sw2.Elapsed);
        Console.WriteLine("  Average: " + TimeSpan.FromTicks((sw1.Elapsed.Ticks + sw2.Elapsed.Ticks) / 2));
    }

    static void Test(bool shouldBeEqual, byte[] a, byte[] b)
    {
        if (shouldBeEqual != AreEqualSafe(a, b))
            throw new Exception();
        if (shouldBeEqual != AreEqualSafeParallel(a, b))
            throw new Exception();
        if (shouldBeEqual != AreEqualUnsafe(a, b))
            throw new Exception();
        if (shouldBeEqual != AreEqualUnsafeParallel(a, b))
            throw new Exception();
        if (shouldBeEqual != AreEqualNative(a, b))
            throw new Exception();
    }

    static void VerifyCorrectness()
    {
        Test(true,
        new byte[] { 1, 2, 3, 4, 5, 6, 7 },
        new byte[] { 1, 2, 3, 4, 5, 6, 7 });

        Test(true,
        new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

        Test(false,
        new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 },
        new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 });
    }


    static void Main(string[] args)
    {
        VerifyCorrectness();

        var length = 1000000;
        var iterations = 10000;

        Console.WriteLine("Length:");
        Console.WriteLine("  " + length.ToString("N"));
        Console.WriteLine("Iterations:");
        Console.WriteLine("  " + iterations.ToString("N"));

        SpeedTest("Safe", length, iterations, AreEqualSafe);
        SpeedTest("SafeParallel", length, iterations, AreEqualSafeParallel);
        SpeedTest("Unsafe", length, iterations, AreEqualUnsafe);
        SpeedTest("UnsafeParallel", length, iterations, AreEqualUnsafeParallel);
        SpeedTest("Native", length, iterations, AreEqualNative);

        Console.ReadLine();
    }
}