加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 对于byte [],安全比较与不安全

发布时间:2020-12-15 21:50:41 所属栏目:百科 来源:网络整理
导读:我已经在不同的地方读过,关于使用固定块的数组之间不安全迭代的速度有多快.我试过.net 4和4.5,或多或少地实现了相同的结果. 安全比较总是更快,有时是一点点,有时几乎是一半时间,特别是在.net 4中. 难道我做错了什么? class Program{ public unsafe static i
我已经在不同的地方读过,关于使用固定块的数组之间不安全迭代的速度有多快.我试过.net 4和4.5,或多或少地实现了相同的结果.
安全比较总是更快,有时是一点点,有时几乎是一半时间,特别是在.net 4中.

难道我做错了什么?

class Program
{
    public unsafe static int UnsafeCompareTo2(byte[] self,byte[] other)
    {
        if (self.Length < other.Length) { return -1; }

        if (self.Length > other.Length) { return +1; }

        GCHandle selfHandle =
            GCHandle.Alloc(self,GCHandleType.Pinned);

        GCHandle otherHandle =
            GCHandle.Alloc(other,GCHandleType.Pinned);

        byte* selfPtr = (byte*)
            selfHandle.AddrOfPinnedObject().ToPointer();

        byte* otherPtr = (byte*)
            otherHandle.AddrOfPinnedObject().ToPointer();

        int length = self.Length;

        int comparison = 0;

        for (int index = 0; index < length; index++)
        {
            comparison =
                (*selfPtr++).CompareTo((*otherPtr++));

            if (comparison != 0) { break; }
        }
        selfHandle.Free();

        return comparison;
    }

    public static int CompareTo(byte[] self,byte[] other)
    {
        if (self.Length < other.Length) { return -1; }

        if (self.Length > other.Length) { return +1; }

        int comparison = 0;

        for (int i = 0; i < self.Length && i < other.Length; i++)
        {
            if ((comparison = self[i].CompareTo(other[i])) != 0)
            { return comparison; }
        }
        return comparison;
    }

    public unsafe static int UnsafeCompareTo(byte[] self,byte[] other)
    {
        if (self.Length < other.Length) { return -1; }

        if (self.Length > other.Length) { return +1; }

        int n = self.Length;

        fixed (byte* selfPtr = self,otherPtr = other)
        {
            byte* ptr1 = selfPtr;
            byte* ptr2 = otherPtr;

            while (n-- > 0)
            {
                int comparison;

                if ((comparison = (*ptr1++).CompareTo(*ptr2++)) != 0)
                {
                    return comparison;
                }
            }   
        }
        return 0;
    }

    static void Main(string[] args)
    {
        byte[] b1 = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 };
        byte[] b2 = { 1,21 };
        Stopwatch watch = new Stopwatch();

        watch.Start();
        int result;
        for(long i = 0; i < Math.Pow(10,2); i++)
            result = CompareTo(b1,b2);
        watch.Stop();
        Console.WriteLine("safe = {0}",watch.Elapsed);
        watch.Restart();
        for (long i = 0; i < Math.Pow(10,2); i++)
            result = UnsafeCompareTo(b1,b2);
        watch.Stop();
        Console.WriteLine("unsafe1 = {0}",2); i++)
            result = UnsafeCompareTo2(b1,b2);
        watch.Stop();
        Console.WriteLine("unsafe2 = {0}",watch.Elapsed);
        Console.ReadLine();
    }
}

解决方法

在我看来,差异经常被开销和随机噪声所淹没.我发现它对于更多的迭代更加突出,更重要的是更长的字节数组.我通过更频繁地避免方法调用开销来制作一个更快的变体:

public unsafe static int UnsafeCompareTo(byte[] self,byte[] other)
{
    if (self.Length < other.Length) { return -1; }

    if (self.Length > other.Length) { return +1; }

    int n = self.Length;

    fixed (byte* selfPtr = self,otherPtr = other)
    {
        byte* ptr1 = selfPtr;
        byte* ptr2 = otherPtr;

        byte b1;
        byte b2;
        while (n-- > 0)
        {
            b1 = (*ptr1++);
            b2 = (*ptr2++);
            if (b1 == b2)
                continue;
            return b1.CompareTo(b2);
        }
    }
    return 0;
}

我还注意到你的代码中有一个错误(不会真的减慢速度),如下所示:

GCHandle otherHandle = GCHandle.Alloc(self,GCHandleType.Pinned);

它应该是使用其他的,它应该在之后释放它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读