【问题标题】:Regex slow on Windows Server 2008Windows Server 2008 上的正则表达式速度慢
【发布时间】:2009-09-29 08:06:01
【问题描述】:

我的正则表达式在 Windows Server 2008 上的编译速度非常慢。我编写了一个小型控制台应用程序来突出这个问题。该应用程序生成自己的输入并从 XML 文件中的单词构建正则表达式。我构建了这个应用程序的发布版本,并在我的个人笔记本电脑(运行 XP)和 Windows 2008 服务器上运行它。正则表达式在我的笔记本电脑上编译需要 0.21 秒,但在服务器上编译需要 23 秒。

任何想法可能导致这种情况?问题仅在第一次使用正则表达式时(第一次编译时 - 之后就可以了)

我还发现了另一个问题 - 在同一 Windows 2008 服务器上的正则表达式中使用 \s+ 时,内存气球(使用 4GB+)和正则表达式的编译永远不会完成。

Regex 和 64 位 .net 是否存在已知问题?是否有可用的修复/补丁?我在网上找不到任何信息,但我在 Framework 2.0 中找到了一些关于同样问题的文章 - 现在肯定已经解决了吗?

更多信息: 服务器运行 .net 框架 (3.5 SP1) 的 64 位版本,在我的笔记本电脑上我安装了 Visual Studio 2008 和 3.5 框架。正则表达式具有以下模式:^word$|^word$|^word$,并使用以下标志构造:RegexOptions.IgnoreCase | RegexOptions.Compiled


这是一个代码sn-p:

StringBuilder regexString = new StringBuilder();
if (!String.IsNullOrEmpty(fileLocation))
{
    XmlTextReader textReader = new XmlTextReader(fileLocation);
    textReader.Read();
    while (textReader.Read())
    {
        textReader.MoveToElement();
        if (textReader.Name == "word")
        {
            regexString.Append("^" + textReader.GetAttribute(0) + "$|");
        }
    }
    ProfanityFilter = new Regex(regexString.ToString(0, regexString.Length - 1), RegexOptions.IgnoreCase | RegexOptions.Compiled);
}

DateTime time = DateTime.Now;
Console.WriteLine("\nIsProfane:\n" + ProfanityFilter.IsMatch("test"));
Console.WriteLine("\nTime: " + (DateTime.Now - time).TotalSeconds);
Console.ReadKey();

这导致我的笔记本电脑上的时间为 0.21 秒,而 2008 服务器上的时间为 23 秒。 XML 文件由 168 个单词组成,格式如下:

<word text="test" />

【问题讨论】:

  • 正则表达式和xml的代码示例怎么样?

标签: c# .net regex


【解决方案1】:

我找到了一个解决方案,虽然不是正确的,但在我的情况下是完美的。出于某种原因,如果我省略 RegexOptions.Compiled 标志,Regex 会快得多。我什至设法在 2008 年的服务器上在 65 毫秒内对 100 个长短语执行 Regex。

这一定是 .net lib 中的错误,因为未编译的版本应该比编译的版本慢得多。无论哪种方式,每次检查不到 1 毫秒对我来说是非常可以接受的 :)

【讨论】:

  • 您可能还想尝试更多替代正则表达式模式以找到最佳模式,例如 /^(word|word|word|word)$/ 而不是 /^word$|^word$ |^word$/ .
  • 是的,我知道这一点。就像我在原始问题中提到的那样,我编写了一个控制台应用程序只是为了突出问题。完全相同的正则表达式在我的笔记本电脑上编译时间为 0.21 秒,因此它不需要在 64 位服务器上编译 23 秒。
  • 有同样的问题和解决方案,它设置为编译它在我的本地 XP 机器上运行良好,当上传到服务器时每个正则表达式需要 40 多秒。删除了编译选项,现在 8 次调用总共不到 1 秒。
  • 编译还是运行?另外,您如何衡量绩效?有 1000 种方法可以错误地做到这一点,这意味着显示错误的结果并做出错误的假设和决定。记住第一次运行的有效负载,还有目标配置(调试|发布)和架构(x86|x64|任何 CPU)——不过这些都是非常基本的时刻。
  • 发生改进的原因是,如果您有Regex.Complied 标志,它将在每次创建实例时编译正则表达式,如果您将其排除在外,它将编译一次然后将其存储在缓存中.经验法则是,如果您使用的是 complied 标志,则必须使用多次创建的对象才能使其物有所值。 Here is another SO Answer 有基准并对其进行更多解释。
【解决方案2】:

您可以使用Regex.CompileToAssembly 方法预编译您的正则表达式,然后您可以将编译好的正则表达式部署到您的服务器。

【讨论】:

  • 是的,但这意味着该服务的非技术管理员不能只在 XML 文件中添加一个词 - 每次都需要重新编译 DLL。不过建议很好。
  • 我认为他的意思是在你读入文件之后,你使用 RegexOptions.Compiled 选项来优化正则表达式的执行。
  • 不,他的意思是您将正则表达式预编译为 DLL 文件(程序集)——这就是 CompileToAssembly 方法的作用。 RegexOptions.Compiled 标志是整个问题的原因。这确实是我想要的方式,但似乎 64 位 .net 库中存在错误。
【解决方案3】:

我遇到了完全相同的问题。我的应用程序在 x86 机器上运行良好,但内存膨胀并在 x64 上挂起。删除编译标志没有帮助。我今天在 .net 4.0 上尝试了这个,问题仍然存在。如果你有repro,我建议你提交一个错误。

我认为 MSFT 知道这一点,见底部comment here

但是让他们决定这是否是同一个错误。如果您提交文件,请在此处添加您提交文件的链接,以便我可以将我的 cmets 添加到其中。

【讨论】:

  • 我在 Windows Server 2008 r2 64 位机器上运行 .NET 4.0 应用程序时遇到了同样的问题。关于这个主题的任何消息?多伦
  • @DoronBM,请对上面的 Microsoft 错误数据库链接发表评论,并与您的 Microsoft 代表一起上报。谢谢!据我所知,还没有解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 2010-10-22
相关资源
最近更新 更多