【问题标题】:OutOfMemoryException in Regex Matches when processing large files处理大文件时正则表达式匹配中的 OutOfMemoryException
【发布时间】:2010-10-18 01:41:15
【问题描述】:

我有一个生产代码版本的异常日志。

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 应用程序。

【问题讨论】:

  • 你能列出使用正则表达式的代码吗?

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


【解决方案1】:

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

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

here 上有一些很好的信息。

【讨论】:

  • 把我的正则表达式放到这个问题上。
  • 你有一个小sn-p 你想要匹配的东西吗?是 Html 还是可能包含 Urls 的文本?
  • 在最新的正则表达式中,如果将最后一个''更改为'会发生什么?'
  • 它的 HTML 只是使用 Yahoo 的源代码,实际上一切都需要很长时间。我现在就试试这个改变。
  • 似乎对我不起作用,正则表达式用 30k html 文件将我的测试程序最大化,用于 Cpu 周期!
【解决方案2】:

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

【讨论】:

  • 你说得对,我刚刚发现并更新了我的示例。这不是原始代码的行为,这是测试代码。查看我的最终编辑。
【解决方案3】:

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

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

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

【讨论】:

  • 2 个问题。我最初使用 SingleLine 作为正则表达式中的选项。因此,逐行阅读可能会破坏一些正则表达式。其次,这将对较短的文件产生不良的性能影响(显然我可以根据大小进行切换,但听起来很脏:)但是如果我无法修复它,这是个好主意)
  • 我敢打赌,小文件的逐行和一次应用正则表达式之间的性能差异将非常小,不会产生明显的影响。
  • 我知道 stringbuilder 对此有好处,但我的意思是使用带有 Regex 的 stringbuilder 听起来像是帮助 RegEx runner 更有效地使用内存,这对我来说是全新的。
  • 这是可能的,我不确定 StringBuilder 是否以某种方式允许 Regex 更有效地工作,但 IMO 这不是你应该依赖的东西。如果您的内存不足,这可能表明应该解决更大的设计问题。
  • 显然我搞砸了我的本地测试,请查看我的最终编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-29
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多