具有大正则表达式的正则表达式源生成器在dotnet构建时导致OutOfMemoryException



我有一个以|分隔的单词列表形式的大正则表达式。整个正则表达式长度为100万字符

[RegexGenerator(@"KnownItem1|KnownItem2|KnownItem3")]
private static partial Regex NamedEntities();

使用dotnet构建导致此错误

CSC : warning CS8785: Generator 'RegexGenerator' failed to generate source. It will not contribute to the output and co
mpilation errors may occur as a result. Exception was of type 'OutOfMemoryException' with message 'Exception of type 'S
ystem.OutOfMemoryException' was thrown.'

当遇到上述错误时,dotnet.exe进程占用了5GB的RAM。我怎样才能使构建成功?我已经搜索了如何增加内存使用的dotnet构建,如何通过不发出调试符号来减少RAM使用,但没有找到解决方案。与运行时的Regex OOM相比,这也是一个不同的情况,在StackOverflow上已经被询问了很多次——这是一个新的Regex源生成器的编译时错误。这个正则表达式在运行时以解释模式工作。

您应该真的不使用regex源生成器。使用regex源生成器获取正则表达式并将其转换为编写的代码,然后在同一程序集中与项目一起编译。当您要求使用给定的正则表达式进行匹配时,最好在试图避免正则表达式引擎启动缓慢时使用它。

然而,RegexOptions.Compiled选项告诉引擎将该表达式编译成一个单独的程序集(与源生成器的方式或多或少相同)。这将在运行时而不是编译时委托正则表达式的编译过程。该选项的目标是避免运行时解释正则表达式,并将其硬编码为性能更好的方法。

TL;博士

对于太大的regex(大约500个字符是大的)使用RegexOptions.Compiled。对于较小的,首选源生成器。

. net正则表达式目前还没有针对这个用例进行优化。本文讨论了Aho-Corasick对这种情况的优化。

现在的解决方法是使用Aho-Corasick并手动消除重叠匹配。

hellover在regex上匹配hello|lover匹配hello

然而,Aho-Corasick匹配hellolover,因此您必须跟踪返回的匹配的索引和长度,并消除lover以模仿regex行为。

最新更新