【问题标题】:Regular expression slow正则表达式慢
【发布时间】:2023-03-17 15:05:01
【问题描述】:

我正在尝试使用正则表达式解析构建日志文件以获取一些信息。我正在尝试使用像("( {9}time)(.+)(c1xx\\.dll+)(.+)s") 这样的正则表达式来匹配像time(D:\Program Files\Microsoft Visual Studio 11.0\VC\bin\c1xx.dll)=0.047s 这样的行

在一个有 19,000 行的文件中,这大约需要 120 秒才能完成。其中一些相当大。基本问题是当我将行数减少到 19000 左右时,使用某些条件,它没有改变任何东西,实际上使情况变得更糟。我不明白,如果我完全删除正则表达式,只扫描文件大约需要6s。这意味着正则表达式是这里主要的耗时过程。那么,当我删除一半的行时,为什么它至少没有降低一些。

另外,谁能告诉我哪种正则表达式更快、更通用或更具体。即,我也可以使用此正则表达式在文件中匹配此行 time(D:\Program Files\Microsoft Visual Studio 11.0\VC\bin\c1xx.dll)=0.047s uniquley - ("(.+)(c1xx.dll)(.+)")。但这会使整个事情运行得更慢,但是当我使用 ("( {9}time)(.+)(c1xx\\.dll+)(.+)") 之类的东西时,它会运行得稍微快一些。

我正在使用 c++ 11 正则表达式库,主要是 regex_match 函数。

regex c1xx("( {9}time)(.+)(c1xx\\.dll+)(.+)s");
auto start = system_clock::now();
int linecount = 0;
while (getline(inFile, currentLine))
{
    if (regex_match(currentLine.c_str(), cppFile))
    {
        linecount++;
        // Do something, just insert it into a vector
    }
}

auto end = system_clock::now();
auto elapsed = duration_cast<milliseconds>(end - start);
cout << "Time taken for parsing first log = " << elapsed.count() << " ms" << " lines = " << linecount << endl;

输出:

解析第一个日志所用的时间 = 119416 毫秒行 = 19617

regex c1xx("( {9}time)(.+)(c1xx\\.dll+)(.+)s");
auto start = system_clock::now();
int linecount = 0;
while (getline(inFile, currentLine))
{
    if (currentLine.size() > 200)
    {
        continue;
    }

    if (regex_match(currentLine.c_str(), cppFile))
    {
        linecount++;
        // Do something, just insert it into a vector
    }
}

auto end = system_clock::now();
auto elapsed = duration_cast<milliseconds>(end - start);
cout << "Time taken for parsing first log = " << elapsed.count() << " ms" << " lines = " << linecount << endl;

输出:

解析第一个日志所用的时间 = 131613 毫秒行 = 9216

为什么在第二种情况下需要更多时间?

【问题讨论】:

  • 代码比英文描述更受欢迎。
  • 第八天,上帝说:“我怎么会在这些废话中找到任何东西?让 grep 吧。”还有 grep。并且有很多欢乐。
  • 那里,几乎所有的代码,我不知道如何将问题的第二部分放入代码中,只是询问哪种类型的正则表达式会更快?一种通用的或更具体的更严格的正则表达式?
  • 您测量的是发布版本,而不是调试版本,对吗?
  • 在不启用优化的情况下衡量性能100% 毫无意义。请参阅this answer 上的 cmets 了解更多说明。

标签: c++ regex visual-c++ c++11 visual-studio-2012


【解决方案1】:

那么为什么当我删除一半的行时,它至少没有降低一些。

为什么在第二种情况下需要更多时间?

可以想象regex 库以某种方式能够比您的大小检查更有效地过滤掉行。在您的 while 循环中引入额外的分支也可能会混淆编译器的分支预测,因此您无法获得最佳的指令流水线/预取。

另外,谁能告诉我哪种正则表达式更快、更通用或更具体。

如果表达式("(.+)(c1xx.dll)(.+)") 可以工作,我相信(".+c1xx\\.dll.+") 也可以工作,并且正则表达式不会为你保存匹配位置。

【讨论】:

  • 第一部分看起来是正确的,但在第二部分你写的两个正则表达式不完全一样吗?我实际上是在问我是否有“ab.+c1xx\\.dll.+cd”作为正则表达式,与“.+c1xx\\.dll.+”相比,它会更快/更慢/没有效果,两者都是唯一的识别我的字符串。感谢您的回答。
  • ".+c1xx\\.dll.+" 肯定更快
猜你喜欢
  • 1970-01-01
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-11
  • 2012-12-21
  • 1970-01-01
相关资源
最近更新 更多