首页 > 解决方案 > 为什么 .NET string.Equals 每个循环检查 5 个字符?(AMD 为 6)

问题描述

在查看 .Net 源代码时发现了一件奇怪的事情String。在Equals帮助器中: https ://referencesource.microsoft.com/#mscorlib/system/string.cs,11648d2d83718c5e ,用于检查字符串相等性的引用,它一次检查四个字节(我认为),但循环的每次迭代都会五个检查,每个进步两个位置。(并且为 AMD 做了六个,这也很奇怪)

我假设这是他们已经完成的一些特定的微优化,但为什么在循环中检查五次而不是循环五次更快?

感觉我解释的不是很好,但是出处在链接里,会更好的解释。

    private unsafe static bool EqualsHelper(String strA, String strB)
    {
        Contract.Requires(strA != null);
        Contract.Requires(strB != null);
        Contract.Requires(strA.Length == strB.Length);

        int length = strA.Length;

        fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
        {
            char* a = ap;
            char* b = bp;

            // unroll the loop
#if AMD64
            // for AMD64 bit platform we unroll by 12 and
            // check 3 qword at a time. This is less code
            // than the 32 bit case and is shorter
            // pathlength

            while (length >= 12)
            {
                if (*(long*)a     != *(long*)b) return false;
                if (*(long*)(a+4) != *(long*)(b+4)) return false;
                if (*(long*)(a+8) != *(long*)(b+8)) return false;
                a += 12; b += 12; length -= 12;
            }
#else
            while (length >= 10)
            {
                if (*(int*)a != *(int*)b) return false;
                if (*(int*)(a+2) != *(int*)(b+2)) return false;
                if (*(int*)(a+4) != *(int*)(b+4)) return false;
                if (*(int*)(a+6) != *(int*)(b+6)) return false;
                if (*(int*)(a+8) != *(int*)(b+8)) return false;
                a += 10; b += 10; length -= 10;
            }
#endif

            // This depends on the fact that the String objects are
            // always zero terminated and that the terminating zero is not included
            // in the length. For odd string sizes, the last compare will include
            // the zero terminator.
            while (length > 0) 
            {
                if (*(int*)a != *(int*)b) break;
                a += 2; b += 2; length -= 2;
            }

            return (length <= 0);
        }
    }

标签: c#.netstringoptimizationmicro-optimization

解决方案


推荐阅读