gpt4 book ai didi

c++ - 为什么 C++ 正则表达式这么慢?

转载 作者:太空狗 更新时间:2023-10-29 23:11:01 26 4
gpt4 key购买 nike

我是 C++ 的新手,必须处理一个文本文件。我决定用正则表达式来做这件事。我想出的正则表达式:

(([^\\s^=]+)\\s*=\\s*)?\"?([^\"^\\s^;]+)\"?\\s*;[!?](\\w+)\\s*

我已经根据以下帖子编写了我的 C++ 代码:

c++ regex extract all substrings using regex_search()

C++代码如下:

#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <chrono>
#include <iterator>

void print(std::smatch match)
{
}

int main()
{
std::ifstream file{ "D:\\File.txt" };
std::string fileData{};

file.seekg(0, std::ios::end);
fileData.reserve(file.tellg());
file.seekg(0, std::ios::beg);

fileData.assign(std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>());

static const std::string pattern{ "(([^\\s^=]+)\\s*=\\s*)?\"?
([^\"^\\s^;]+)\"?\\s*;[!?](\\w+)\\s*" };
std::regex reg{ pattern };
std::sregex_iterator iter(fileData.begin(), fileData.end(), reg);
std::sregex_iterator end;

const auto before = std::chrono::high_resolution_clock::now();

std::for_each(iter, end, print);

const auto after = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> delta = after - before;
std::cout << delta.count() << "ms\n";

file.close();
}

我正在处理的文件包含 541 行。上面的程序需要 5 秒才能获得所有 507 个匹配项。我以前在 C# 中做过这样的事情,但从来没有这么慢的正则表达式。所以我在 C# 中尝试了同样的事情:

var filedata = File.ReadAllText("D:\\File.txt", Encoding.Default);

const string regexPattern =
"(([^\\s^=]+)\\s*=\\s*)?\"?([^\"^\\s^;]+)\"?\\s*;[!?](\\w+)\\s*";

var regex = new Regex(regexPattern, RegexOptions.Multiline |
RegexOptions.Compiled );
var matches = regex.Matches(filedata);

foreach (Match match in matches)
{
Console.WriteLine(match.Value);
}

这只需要 500 毫秒就可以找到所有 507 个匹配项并在控制台上打印出来。因为我必须使用 C++,所以我需要更快。

如何使我的 C++ 程序更快?我做错了什么?

最佳答案

我提到了 C 风格的字符串,但我并不是说尽可能多地使用纯 C 风格可以提高正则表达式的性能。我的意思很简单,我们应该能够在编译时做更多的事情,而在运行时对 std::string 做更少的操作,这样我们可以获得更好的性能。

原始答案

如您所知,我们有两种类型的字符串:C 风格字符串和 std::string

std::string 可以在我们编码时使用,但我们可以说它是一种沉重的东西(这就是为什么有些人不喜欢它)。首先,std::string 使用了堆内存,这意味着它使用了 newmalloc;其次,std::string 在其大小增加时使用了某种特定算法(将当前大小加倍并将当前内容移动到新内存区域并释放旧内存区域)。这些会导致性能问题。

正则表达式显然都是关于字符串的,它需要到处玩字符串。 std::regexstd::string 有很大的关系,所以std::regex 的性能不好。

此外,std::string 完全是运行时的东西。例如,您可以在编译时初始化 C 风格的字符串,但不能在编译时初始化 std::string。这意味着关于 std::string 的东西很少能在编译时优化。这是一个关于我们如何利用编译时间在运行时获得非常好的性能的示例:Why is initialization of variable with constexpr evaluated at runtime instead of at compile time

std::regex 在编译时不能做很多事情,因为它使用 std::string,这也可能导致性能问题。这就是人们可能喜欢 CTRE(编译时正则表达式)库的原因。

如果std::regex的源代码中可以使用std::string_view,我认为性能会更好。

C++ promise :“不要为你不用的东西付费。”没有冒犯任何人的意思,但我个人认为 std::regex 违背了 promise 。如果 C++ 标准委员会认为功能比其他任何东西都重要,我会说为什么不使用 Java。

关于c++ - 为什么 C++ 正则表达式这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52697265/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com