这是对代码路径的一些微基准测试,该代码路径每纳秒要经过数百万亿次遍历,并且需要快速进行。

对于下面的代码段,比较

  • x.EndsWith(y, InvariantCulture)
  • Regex(y, Compiled | CultureInvariant).IsMatch(x)

  • 我得到以下数字:
    =============================
    Regex   : 00:00:01.2235890. Ignore this: 16666666
    EndsWith: 00:00:03.2194626. Ignore this: 16666666
    =============================
    Regex   : 00:00:01.0979105. Ignore this: 16666666
    EndsWith: 00:00:03.2346031. Ignore this: 16666666
    =============================
    Regex   : 00:00:01.0687845. Ignore this: 16666666
    EndsWith: 00:00:03.3199213. Ignore this: 16666666
    

    换句话说,EndsWith需要的时间是Regex的3倍。

    我应该注意,根据使用的字符串值,我尝试了其他值和,有时EndsWith更快,有时Regex
    EndsWith(x, InvariantCulture)归结为一些参数检查,然后是 extern int nativeCompareOrdinalEx(String, int, String, int, int) ,我希望它很快。 (正如@nhahtdh正确指出的,在InvariantCulture的情况下,它称为CultureInfo.InvariantCulture.CompareInfo.IsSuffix which calls InternalFindNLSStringEx。我不小心遵循了Ordinal路径)

    N.B. :我刚刚发现,使用Ordinal而不是InvariantCulture调用EndsWith时,EndsWith比Regex快得多……不幸的是,没有RegexOptions.Ordinal可以与之比较。

    我还期望编译后的正则表达式很快,但是如何击败专用方法呢?

    乐码:
    string[] BunchOfIDs =
    {
        "zxc@x@432143214@O@abcße",
        "zxc@x@432143214@T@abcßX",
        "qwe@x@432143214@O@abcße",
        "qwe@x@432143214@XXabc",
        "zxc@x@1234@O@aXcße",
        "qwe@y@1234@O@aYcße",
    };
    
    var endsWith = "@abcße";
    var endsWithRegex = new Regex("@abcße$", RegexOptions.None);
    
    int reps = 20000000;
    for (int i = 0; i < 3; i++)
    {
        Console.WriteLine("=============================");
        int x = 0;
        var sw = Stopwatch.StartNew();
        for (int j = 0; j < reps; j++)
        {
            x += BunchOfIDs[j % BunchOfIDs.Length].EndsWith(endsWith, StringComparison.InvariantCulture) ? 1 : 2;
        }
        Console.WriteLine("EndsWith: " + sw.Elapsed + ". Ignore this: " + x);
    
        x = 0;
        sw = Stopwatch.StartNew();
        for (int j = 0; j < reps; j++)
        {
            x += endsWithRegex.IsMatch(BunchOfIDs[j % BunchOfIDs.Length]) ? 1 : 2;
        }
        Console.WriteLine("Regex   : " + sw.Elapsed + ". Ignore this: " + x);
    }
    

    最佳答案

    有可能

    因为 StringComparison.InvariantCulture != RegexOptions.CultureInvariant !

    这个片段

    var str = "ss";
    var endsWith = "ß";
    var endsWithRegex = new Regex("ß$",
        RegexOptions.Compiled | RegexOptions.CultureInvariant);
    Console.WriteLine(str.EndsWith(endsWith, StringComparison.InvariantCulture)
        + " vs "
        + endsWithRegex.IsMatch(str));
    

    打印
    True vs False
    

    因此,看起来RegexOptions.CultureInvariant并不暗示StringComparison.InvariantCulture所隐含的内容。 RegexOptions.CultureInvariant是否更像StringComparison.Ordinal?

    关于.net - 为什么regex.IsMatch(str)比str.EndsWith(不变文化)快?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27958053/

    10-12 06:49