正则表达式中的OutOfMemoryException匹配处理大型文件时

时间:2009-04-07 13:50:30

标签: .net regex performance memory out-of-memory

我从其中一个生产代码版本中获得了异常日志。

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Text.RegularExpressions.Match..ctor(Regex regex, Int32 capcount, String text, Int32 begpos, Int32 len, Int32 startpos)
   at System.Text.RegularExpressions.RegexRunner.InitMatch()
   at System.Text.RegularExpressions.RegexRunner.Scan(Regex regex, String text, Int32 textbeg, Int32 textend, Int32 textstart, Int32 prevlen, Boolean quick)
   at System.Text.RegularExpressions.Regex.Run(Boolean quick, Int32 prevlen, String input, Int32 beginning, Int32 length, Int32 startat)
   at System.Text.RegularExpressions.MatchCollection.GetMatch(Int32 i)
   at System.Text.RegularExpressions.MatchEnumerator.MoveNext()

它试图处理的数据大约是800KB。

在我的本地测试中它完全正常。你有没有见过类似的行为,可能是什么原因?

我应该在处理之前拆分文本,但显然在这种情况下正则表达式可能不匹配,因为原始文件是从随机位置拆分的。

我的正则表:

编辑2:

我认为这个特殊的RegEx导致了这个问题,当我在一个孤立的环境中测试它时,它会立即占用内存。

((?:( |\.\.|\.|""|'|=)[\/|\?](?:[\w#!:\.\?\+=&@!$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})*)( |\.|\.\.|""|'| ))?

编辑

我的本​​地测试错了。我正在加载一个大字符串,然后将内容添加到它,这使得.NET Framework头晕,然后在RegEx期间而不是在字符串操作期间(或随机地,因为忽略我之前说过的东西)给出OOM异常。

这是一个.NET Framework 2.0应用程序。

3 个答案:

答案 0 :(得分:2)

没有看到你的正则表达式,我不确定,但有时你会遇到这样的问题,因为你的比赛是贪婪而不是懒惰。

Regex引擎必须在内部存储大量信息,而贪婪匹配最终会导致正则表达式选择800k字符串的大部分,多次结束。

有关here的一些很好的信息。

答案 1 :(得分:1)

如果您的应用程序可以,我会尝试的第一件事就是分割输入。

是否可以逐行读取文件(如果输入是文件),以这种方式应用正则表达式?

你应该看看CLR Profiler。学习如何使用可能需要一些时间,但这是值得的。它将帮助您可视化对象使用的内存量。

答案 2 :(得分:1)

根据您的编辑,听起来您的代码可能正在创建占用大量内存的字符串。这意味着即使内存不足异常是从Regex代码中生成的,但实际上并不是因为Regex本身占用了太多内存。因此,如果在您自己的代码中使用StringBuilder解决了问题,那么您应该这样做。