4

由于高内存使用率,以下代码在一段时间后崩溃(我打开任务管理器并且其使用的内存不断增加)。但我看不到任何内存泄漏,除了垃圾收集没有完成它的工作。有什么建议么?

//Load a list of regex
//Load a list of phrases
//Open a output file

foreach (string regexString in regexList)
{
    int num = 0;

    Regex regex = new Regex(regexString, RegexOptions.Compiled | RegexOptions.IgnoreCase);

    foreach (string phrase in phraseList)
            num += regex.Matches(phrase).Count;

    if (num > 0)
    {
        output.WriteLine(String.Join(" ", num, phrase));
        output.Flush();
    }
}

编辑:

完整代码: http: //pastebin.com/0SQYn44z

编辑2:

我找到并发布了解决方案(foreach 循环)感谢所有试图提供帮助的人。

4

5 回答 5

6

我无法从您的示例中看出,但RegexOptions.Compiled标志可能会导致问题。来自 msdn:

Compiled 指定将正则表达式编译为程序集。这会产生更快的执行速度,但会增加启动时间。调用 CompileToAssembly 方法时,不应将此值分配给 Options 属性。

如果将正则表达式编译为程序集,则在重新启动应用程序之前无法卸载生成的代码,因为 .Net 不会卸载程序集。

这意味着如果您有很多不同的正则表达式,并且您不重用它们,那么编译的正则表达式通常不是一个好主意。

于 2012-06-24T01:58:10.277 回答
2

您的正则表达式可能会使用过多的回溯,从而导致执行时间长和内存使用量高

您可以发布正则表达式和输入,以便我可以确定吗?

于 2012-06-24T01:54:59.063 回答
1

看到你的代码后,我已经可以推荐不要使用两个,而是一个组合的正则表达式。就像是:

Regex regex = new Regex(
        @"\b(?:" + s1 + " " + s2 + "|" + s2 + " " + s1 + @")\b",
        RegexOptions.IgnoreCase);

请注意,那里的一系列+运算符将转换为单个String.Concat(params string[])调用。只有 2 到 4 个部分,它甚至不会创建临时数组,因为Concat这种情况下有更多专门的重载。Join总是使用一个临时数组并且还需要处理分隔符字符串,即使它是空的。

您可能要记住的另一件事是,在调试模式下运行程序与在发布模式下运行程序有很大不同。例如,该keywords列表将保持活动状态,直到函数返回。我建议明确限制其生命周期并尽快清理其他对象。可能类似于以下内容:

string[] keywordArray;
using (StreamReader keywordsFile = new StreamReader("keywords.txt"))
{
    List<string> keywords = new List<string>();
    string keyword;
    while ((keyword = keywordsFile.ReadLine()) != null)
        keywords.Add(keyword);

    keywordArray = keywords.ToArray();
}

或者完全跳过它:

string[] keywordArray = File.ReadAllLines("keywords.txt"); // internally uses above code

但是,不知何故,我觉得将您的巨大提要文件作为一个整体加载到内存中是一个坏主意。FeedItem如果您可以一次反序列化一个并从迭代器方法中返回它,则需要的内存会少得多。然后,您需要做的就是重组算法以将提要项目的循环作为最外层循环。

于 2012-06-24T07:11:18.473 回答
1

让我们看看我是否做对了。您有一个很大的关键字列表,并且对于其中两个单词的每个排列,您通过将它们连接在一起并在中间有一个空格来创建一个新字符串,再加上另一个单词顺序颠倒的字符串(这是不必要的,顺便说一句) . 最后,您从每个字符串创建一个 Regex 对象。

完成此操作后,您开始遍历 FeedItem 对象列表,获取每个对象的两个属性并将它们形成一个字符串,就像您对关键字所做的那样,并尝试将该字符串与两个正则表达式中的每一个进行匹配。简而言之,我认为您应该暂时搁置指责并专注于重构您的代码。事实上,我建议你暂时忘记正则表达式。你没有使用他们的任何力量,他们正在分散你对真正问题的注意力。

于 2012-06-24T07:54:18.583 回答
1

您可以使用一些无需调用 Dipose() 即可实现 IDisposable 的类型:

  • 流阅读器
  • StreamWriter
  • XmlReader

将这些类型的使用包装在 using 语句中,看看这是否对您有所改善。

于 2012-06-24T02:41:29.880 回答