为什么我的正则表达式比编译时编译得慢得多?

mik*_*kel 19 c# regex performance

我有一个庞大而复杂的C#正则表达式,在解释时运行正常,但有点慢.我试图通过设置加快速度RegexOptions.Compiled,这似乎是第一次约30秒,之后立即.我试图通过首先将正则表达式编译为程序集来否定这一点,所以我的应用程序可以尽可能快.

我的问题是编译延迟发生时,是否在应用程序中编译:

Regex myComplexRegex = new Regex(regexText, RegexOptions.Compiled);
MatchCollection matches = myComplexRegex.Matches(searchText);
foreach (Match match in matches) // <--- when the one-time long delay kicks in
{

} 
Run Code Online (Sandbox Code Playgroud)

或提前使用Regex.CompileToAssembly:

MatchCollection matches = new CompiledAssembly.ComplexRegex().Matches(searchText);
foreach (Match match in matches) // <--- when the one-time long delay kicks in
{

} 
Run Code Online (Sandbox Code Playgroud)

这使得编译程序基本没用,因为我仍然在第一次foreach调用时遇到延迟.我想要的是所有的编译延迟都是在编译时完成的(在Regex.CompileToAssembly调用中),而不是在运行时.我哪里错了?

(我用来编译成程序集的代码类似于 http://www.dijksterhuis.org/regular-expressions-advanced/,如果相关的话).

编辑:

new在调用编译的程序集时我应该使用new CompiledAssembly.ComplexRegex().Matches(searchText);吗?但它没有提供"需要对象引用"错误.

更新2

谢谢你的回答/评论.我正在使用的正则表达式很长但基本上很简单,列出了数千个单词,每个单词用|分隔.我真的看不出这是一个回溯问题.主题字符串可以只有一个字母长,它仍然可以导致编译延迟.对于RegexOptions.Compiled正则表达式,当正则表达式包含5000个单词时,执行将需要10秒以上.为了比较,正则表达式的非编译版本可以使用30,000多个单词,并且仍然可以立即执行.

在对此进行了大量测试后,我认为我发现的是:

  • 当你的正则表达式有很多选择时,不要使用RegexOptions.Compiled - 它的编译速度可能非常慢.
  • .Net会在可能的情况下对正则表达式使用惰性求值,AFAI也可以看到这也扩展(至少在某种程度上)到正则表达式编译.正则表达式只有在必要时才会完全编译,并且似乎无法提前强制编译.
  • 如果可以强制完全编译正则表达式,Regex.CompileToAssembly会更有用,它似乎正在接近无意义.

如果我错了或遗漏了什么,请纠正我!

dri*_*iis 7

使用时RegexOptions.Compiled,应确保重新使用Regex对象.看起来你好像不这样做.

RegexOptions.Compiled是一种权衡.正则表达式的初始构造将更慢,因为代码是即时编译的,但每个匹配应该更快.如果正则表达式在运行时更改,则使用RegexOptions.Compiled可能没有任何好处,尽管它可能取决于所涉及的实际表达式.

根据评论更新

如果你的实际代码看起来像你发布的代码,那么你没有任何优势CompileToAssembly,因为每次运行这段代码时你都会创建新的,正在运行的Regex实例.为了利用CompileToAssembly,您需要先编译Regex; 然后获取生成的程序集并在项目中引用它.然后,您应该实例化生成的生成的强类型Regex类型.

在您链接到的示例中,他有一个名为FindTCPIP的正则表达式,它被编译为名为FindCTPIP的类型.当需要使用时,应该创建此特定类型的新实例,例如:

TheRegularExpressions.FindTCPIP MatchTCP = new TheRegularExpressions.FindTCPIP();
Run Code Online (Sandbox Code Playgroud)


Dou*_*las 2

尝试使用Regex.CompileToAssembly,然后链接到程序集,以便您可以构造 Regex 对象。RegexOptions.Compiled是一个运行时选项,每次运行应用程序时,正则表达式仍会重新编译。

  • 您能否更新您的问题以表明这一点?如果您正在执行“new Regex”,那么您正在构造新的、未编译的 Regex 实例。您需要使用正则表达式程序集中的类。 (3认同)