.net - 为什么 regex.IsMatch(str) 比 str.EndsWith(不变文化)快?

标签 .net regex string performance

这是每纳秒遍历无数次并且需要快速的代码路径的一些微基准测试。

对于下面的代码片段,比较

  • 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需要 3 倍的时间 Regex .

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

    注意 :我刚刚发现当用 Ordinal 调用 EndsWith 时而不是 InvariantCulture , 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/

    相关文章:

    c# - 多线程应用程序中的异常。

    python - 使用 RegEx 在文件中查找变量

    java - 正则表达式检测 html 标签并替换一些

    c# - c# 100个应用同时写入日志时如何实现同步

    c# - 使用 Windows API 从富文本控件检索文本的正确方法是什么?

    java - 如何检查数据库的 URL 是否有效?

    string - Perl Text::CSV_XS 从字符串中读取

    java - 字符串文字池是对字符串对象的引用的集合,还是对象的集合

    c - 打开文本文件并在 C 中搜索字符串后无输出

    c# - ReSharper 使用 SqlDataReader 显示警告