c#比较字符串的最快方法

Coo*_*Bro 19 c# string performance

我注意到了

string1.Length == string2.Length && string1 == string2
Run Code Online (Sandbox Code Playgroud)

在大字符串上比稍微快一点

string1 == string2
Run Code Online (Sandbox Code Playgroud)

这是真的?在比较实际字符串之前比较大字符串长度是一种很好的做法吗?

usr*_*usr 19

strings运算符等于在比较字符之前进行长度检查.所以你不要用这个技巧保存内容的比较.您可能仍然会节省一些CPU周期,因为您的长度检查假定字符串不为空,而BCL必须检查它.因此,如果长度在大多数时间不相等,您将短路一些指令.

不过,我可能在这里错了.也许操作员内联并且检查优化了.谁知道肯定?(他测量的人.)

如果您关心保存每个周期,您可能应该首先使用不同的策略.也许托管代码甚至不是正确的选择.鉴于此,我建议使用较短的表格,而不是使用额外的支票.

  • `因此,如果长度在大多数时间不相等,你会短路一些指令.现在这是一个统计问题 (3认同)

Hab*_*bib 15

String.Equality运算符==内部调用string.Equals,因此使用string.Equals==由框架提供.它已经足够优化了.

它首先比较引用,然后是长度,然后是实际字符.

你可以在这里找到源代码

代码:(来源:http://www.dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/String@cs/1305376/String @cs)

// Determines whether two strings match.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public override bool Equals(Object obj) {
    if (this == null)                        //this is necessary to guard against reverse-pinvokes and
        throw new NullReferenceException();  //other callers who do not use the callvirt instruction

    String str = obj as String;
    if (str == null)
        return false;

    if (Object.ReferenceEquals(this, obj))
        return true;

    return EqualsHelper(this, str);
}
Run Code Online (Sandbox Code Playgroud)

[System.Security.SecuritySafeCritical]  // auto-generated
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private unsafe static bool EqualsHelper(String strA, String strB)
{
    Contract.Requires(strA != null);
    Contract.Requires(strB != null);
    int length = strA.Length;
    if (length != strB.Length) return false;

    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) break;
            if (*(long*)(a+4) != *(long*)(b+4)) break;
            if (*(long*)(a+8) != *(long*)(b+8)) break;
            a += 12; b += 12; length -= 12;
        }
 #else
        while (length >= 10)
        {
            if (*(int*)a != *(int*)b) break;
            if (*(int*)(a+2) != *(int*)(b+2)) break;
            if (*(int*)(a+4) != *(int*)(b+4)) break;
            if (*(int*)(a+6) != *(int*)(b+6)) break;
            if (*(int*)(a+8) != *(int*)(b+8)) break;
            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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @ItNotALie不,`==`比较参考AND值.C#不是Java (5认同)
  • 为什么选票呢?向下滚动到EqualsHelpers,看看这是实际发生的事情! (2认同)

use*_*973 7

我的测试结果

将10000个字符串与10000个其他字符串进行比较,长度相同(256)

时间(s1 == s2):32536889蜱虫

时间(s1.Length == s2.Length)&&(s1 == s2):37380529 ticks

比较10000个字符串到10000个其他字符串随机长度最大256

时间(s1 == s2):27223517滴答

时间(s1.Length == s2.Length)&&(s1 == s2):23419529 ticks

比较10000个字符串到10000个其他字符串随机长度最小值256最大512

时间(s1 == s2):28904898蜱

时间(s1.Length == s2.Length)&&(s1 == s2):25442710 ticks

我觉得令人难以置信的是,比较10000个相等长度的字符串将比比较相同数量的更大数据需要更长的时间.

所有这些测试都是使用完全相同的数据完成的.


Fre*_* 24 6

对于我们中的极客,这里有一个页面,它在对多种比较字符串的方法进行基准测试方面做得很好。

简而言之,最快的方法似乎是 CompareOrdinal:

if (string.CompareOrdinal(stringsWeWantToSeeIfMatches[x], stringsWeAreComparingAgainst[x]) == 0)
{
//they're equal
}
Run Code Online (Sandbox Code Playgroud)

第二种最好的方法似乎是使用带有“键”的字典或哈希集作为要比较的字符串。

读起来很有趣。