正则表达缓慢

时间:2012-06-21 23:56:04

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

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

之类的行

这需要大约120秒来完成,在一个有19,000行的文件中。其中一些非常大。基本问题是当我将行数减少到大约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库,主要是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;

输出:

  

解析第一个log = 119416 ms行= 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;

输出:

  

解析第一个log = 131613 ms行= 9216

所花费的时间

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

1 个答案:

答案 0 :(得分:2)

  

所以当我删除一半的行时,为什么不会降低至少一些量。

     

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

可以想象regex库在某种程度上能够比您的尺寸检查更有效地过滤掉线条。在while循环中引入附加分支也可能会混淆编译器的分支预测,因此您无法获得最佳指令流水线/预取。

  

此外,任何人都可以告诉我什么样的正则表达式更快,更通用一个或多个特定的表达式。

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