Vb.net 比较两字节数组的最快方法是什么?

Vb.net 比较两字节数组的最快方法是什么?,vb.net,arrays,compare,Vb.net,Arrays,Compare,我试图比较VB.NET中的两个长字节数组,但遇到了一个障碍。比较两个50兆字节的文件几乎需要两分钟,所以我显然做错了什么。我在一台拥有大量内存的x64机器上,因此没有任何问题。下面是我目前正在使用的代码,我想对其进行更改 \u Bytes和项。Bytes是要比较的两个不同数组,它们的长度已经相同 For Each B In item.Bytes If B <> _Bytes(I) Then Mismatch = True Exit For

我试图比较VB.NET中的两个长字节数组,但遇到了一个障碍。比较两个50兆字节的文件几乎需要两分钟,所以我显然做错了什么。我在一台拥有大量内存的x64机器上,因此没有任何问题。下面是我目前正在使用的代码,我想对其进行更改

\u Bytes
项。Bytes
是要比较的两个不同数组,它们的长度已经相同

For Each B In item.Bytes
   If B <> _Bytes(I) Then
        Mismatch = True
        Exit For
   End If
   I += 1
Next
用于项中的每个B。字节
如果B_字节(I),则
不匹配=真
退出
如果结束
I+=1
下一个
我需要能够以尽可能快的速度比较可能是数百兆字节甚至可能是一两千兆字节的文件。有什么建议或算法能够更快地做到这一点

Item.bytes
是从数据库/文件系统获取的对象,返回用于比较,因为其字节长度与用户要添加的项匹配。通过比较这两个阵列,我可以确定用户是否向数据库添加了新的内容,如果没有,我可以将它们映射到另一个文件,而不浪费硬盘空间

[更新]


我将数组转换为Byte()的局部变量,然后做了相同的比较,相同的代码,它在一秒钟内运行(我仍然需要对它进行基准测试,并将它与其他数组进行比较),但是如果对局部变量做同样的事,并使用通用数组,它会变得非常慢。我不知道为什么,但这给我提出了更多关于数组使用的问题。

如果不需要知道字节,请使用64位整数,一次得到8。事实上,一旦你把它分成一组8,你就可以找出错误的字节

使用:

或对于整数数组:

Dim count As Integer = binReader.Read(testArray, 0, 3)
\u字节(I)
调用在做什么?它不是每次都加载文件,是吗?即使使用缓冲,这也是个坏消息

有很多方法可以从一次查看long、可能使用不安全代码等方面对其进行微观优化,但我只想先获得合理的性能。很明显,发生了一些非常奇怪的事情

我建议您将比较代码提取到一个单独的函数中,该函数使用两个字节数组。这样你就知道你不会做任何奇怪的事。在这种情况下,我也会对循环使用一个简单的
,而不是对每个
使用
——这样会更简单。哦,首先检查长度是否正确:)

编辑:下面是我将使用的代码(未经测试,但足够简单)。现在是C#格式-我马上转换:

public static bool Equals(byte[] first, byte[] second)
{
    if (first == second)
    {
        return true;
    }
    if (first == null || second == null)
    {
        return false;
    }
    if (first.Length != second.Length)
    {
        return false;
    }
    for (int i=0; i < first.Length; i++)
    {
        if (first[i] != second[i])                
        {
            return false;
        }
    }
    return true;
}
公共静态bool等于(字节[]第一,字节[]第二)
{
如果(第一个==第二个)
{
返回true;
}
if(first==null | | second==null)
{
返回false;
}
if(first.Length!=second.Length)
{
返回false;
}
for(int i=0;i
编辑:下面是VB:

Public Shared Function ArraysEqual(ByVal first As Byte(), _
                                   ByVal second As Byte()) As Boolean
    If (first Is second) Then
        Return True
    End If

    If (first Is Nothing OrElse second Is Nothing) Then
        Return False
    End If
    If  (first.Length <> second.Length) Then
         Return False
    End If

    For i as Integer = 0 To first.Length - 1
        If (first(i) <> second(i)) Then
            Return False
        End If
    Next i
    Return True
End Function
公共共享函数ArraysEqual(ByVal首先作为Byte()_
ByVal second作为Byte())作为布尔值
如果(第一个是第二个),那么
返回真值
如果结束
如果(第一个什么都不是或者第二个什么都不是),那么
返回错误
如果结束
如果(第一个长度第二个长度)那么
返回错误
如果结束
对于i,整数=0到第一个。长度-1
如果(第一(i)第二(i))那么
返回错误
如果结束
接下来我
返回真值
端函数

我认为有两件事可能会有所帮助:

首先,不要总是以item.Bytes的形式访问第二个数组,而是使用局部变量直接指向数组。也就是说,在开始循环之前,请执行以下操作:

 array2 = item.Bytes
For i = 1 to max Step 1
   If (array1(i) <> array2(i)) 
       Exit For
   EndIf 
Next
这将节省每次需要一个字节时从对象取消引用的开销。在VisualBasic中,这可能会很昂贵,尤其是在该属性上有Getter方法的情况下

此外,使用“确定循环”而不是“for each”。您已经知道数组的长度,所以只需使用该值对循环进行编码。这将避免将数组作为集合处理的开销。循环看起来像这样:

 array2 = item.Bytes
For i = 1 to max Step 1
   If (array1(i) <> array2(i)) 
       Exit For
   EndIf 
Next
对于i=1到最大步骤1
If(阵列1(i)阵列2(i))
退出
恩迪夫
下一个

与比较算法没有严格关系:


您确定瓶颈与可用内存和加载字节数组所用的时间无关吗?加载两个2GB字节的数组只是为了比较它们,这可能会让大多数机器感到不安。如果程序设计允许,请尝试使用streams来读取较小的数据块。

比较大小相同的两个字节数组的最快方法是使用interop。在控制台应用程序上运行以下代码:

using System;
using System.Runtime.InteropServices;
using System.Security;

namespace CompareByteArray
{
    class Program
    {
        static void Main(string[] args)
        {
            const int SIZE = 100000;
            const int TEST_COUNT = 100;

            byte[] arrayA = new byte[SIZE];
            byte[] arrayB = new byte[SIZE];

            for (int i = 0; i < SIZE; i++)
            {
                arrayA[i] = 0x22;
                arrayB[i] = 0x22;
            }

            {
                DateTime before = DateTime.Now;
                for (int i = 0; i < TEST_COUNT; i++)
                {
                    int result = MemCmp_Safe(arrayA, arrayB, (UIntPtr)SIZE);

                    if (result != 0) throw new Exception();
                }
                DateTime after = DateTime.Now;

                Console.WriteLine("MemCmp_Safe: {0}", after - before);
            }

            {
                DateTime before = DateTime.Now;
                for (int i = 0; i < TEST_COUNT; i++)
                {
                    int result = MemCmp_Unsafe(arrayA, arrayB, (UIntPtr)SIZE);

                    if (result != 0) throw new Exception();
                }
                DateTime after = DateTime.Now;

                Console.WriteLine("MemCmp_Unsafe: {0}", after - before);
            }


            {
                DateTime before = DateTime.Now;
                for (int i = 0; i < TEST_COUNT; i++)
                {
                    int result = MemCmp_Pure(arrayA, arrayB, SIZE);

                    if (result != 0) throw new Exception();
                }
                DateTime after = DateTime.Now;

                Console.WriteLine("MemCmp_Pure: {0}", after - before);
            }
            return;
        }

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint="memcmp", ExactSpelling=true)]
        [SuppressUnmanagedCodeSecurity]
        static extern int memcmp_1(byte[] b1, byte[] b2, UIntPtr count);

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "memcmp", ExactSpelling = true)]
        [SuppressUnmanagedCodeSecurity]
        static extern unsafe int memcmp_2(byte* b1, byte* b2, UIntPtr count);

        public static int MemCmp_Safe(byte[] a, byte[] b, UIntPtr count)
        {
            return memcmp_1(a, b, count);
        }

        public unsafe static int MemCmp_Unsafe(byte[] a, byte[] b, UIntPtr count)
        {
            fixed(byte* p_a = a)
            {
                fixed (byte* p_b = b)
                {
                    return memcmp_2(p_a, p_b, count);
                }
            }
        }

        public static int MemCmp_Pure(byte[] a, byte[] b, int count)
        {
            int result = 0;
            for (int i = 0; i < count && result == 0; i += 1)
            {
                result = a[0] - b[0];
            }

            return result;
        }

    }
}
使用系统;
使用System.Runtime.InteropServices;
使用系统安全;
命名空间比较字节数组
{
班级计划
{
静态void Main(字符串[]参数)
{
常数int SIZE=100000;
常数int测试计数=100;
字节[]数组=新字节[大小];
byte[]arrayB=新字节[大小];
对于(int i=0;i