通过多次调用Regex来优化性能.IsMatch用于大文本

本文关键字:IsMatch 性能 用于 文本 优化 调用 Regex | 更新日期: 2023-09-27 18:03:02

我有一个很长的文本(50-60 KB),我需要对它运行几个正则表达式(总共大约100条规则)。然而,这是如此之慢,它基本上不能工作。

我所做的只是围绕规则创建一个循环,其中每个规则执行一个Regex.IsMatch()

有办法优化这个吗?

每个规则所做的样例代码:

public class SomeRegexInterceptor : ValidatorBase
    {
        private readonly Regex _rgx = new Regex("some regex", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); 
        public override void Intercept(string html, ValidationResultCollection collection)
        {
            if (!_rgx.IsMatch(html)) return;
            /* do something irrelevant here */
        }
    }

通过多次调用Regex来优化性能.IsMatch用于大文本

关于使用Regex替换的最重要的事情是如何以及在哪里声明Regex。永远不要在循环中初始化Regex对象

创建一个静态类并添加public static readonly Regex字段,RegexOptions.Compiled标志集

然后,在需要的地方使用它们,例如使用MyRegexClass.LeadingWhitespace.Replace(str, string.Empty)

请注意,如果您需要使用Regex.Replace,则不需要检查之前是否与Regex.IsMatch匹配。

阅读并遵循。net框架中正则表达式最佳实践的建议,即:

  • 考虑输入源
  • 正确处理对象实例化
  • 负责回溯
  • 使用超时值
  • 仅在必要时捕获

另外,考虑逐行处理文件,尽量避免使用正则表达式。

你能把你的规则合并成一个规则吗?例如:如果你正在为"aaa"做一个正则表达式,然后为"bbb"做一个正则表达式,合并成"aaa|bbb"可以极大地提高性能(而不是运行两个单独的正则表达式)。我以前以这种方式编程地组合了大量的正则表达式,它使性能产生了巨大的差异。

组合表达式

如果您有能力在运行规则之前完成工作,您可以将正则表达式与|结合起来,并一次完成搜索。然后在你的规则中,你不像以前那样匿名检查匹配,而是根据组的名称。例如

>((?<Ex1>expression1)|(?<Ex2>expression2)|(?<Ex3>expression3))

规则关心组Ex1,它检查这个组。关心Ex2的规则检查Ex2,以此类推。

此外,您可能会分析一组正则表达式并以某种方式对它们进行优化。这将是一个相当了不起的编程壮举,除非你做一些简单的事情,如消除重复。

缓存,缓存大小

另一个想法是缓存和编译所有的正则表达式一次,改变Regex.CacheSize的大小,看看它是否有帮助。文档说明默认值是15,但是您超过了这个值。

更多信息

关于实例化和编译一次表达式的注释是有效的,即使是那个大的注释也是有效的。MSDN提供了其他建议