【问题标题】:Why is std::regex notoriously much slower than other regular expression libraries?为什么 std::regex 比其他正则表达式库慢得多?
【发布时间】:2022-01-04 18:22:15
【问题描述】:

This Github repository 将 std::regex 添加到正则表达式引擎列表并被其他引擎淘汰。

为什么在 libstdc++ 中实现的 std::regex 比其他的慢得多?这是因为 C++ 标准要求,还是只是特定的实现没有得到很好的优化?

同样在枪战中,std::regex 无法编译所有其他人都接受的几个正则表达式,即使在添加标志 std::regex::extended 之后也是如此。他们是(?i)Twain\b\w+nn\b(?i)Tom|Sawyer|Huckleberry|Finn\s[a-zA-Z]{0,12}ing\s([A-Za-z]awyer|[A-Za-z]inn)\s\p{Sm}

更新:添加了与 boost::regex 的比较。

UPDATE2:添加了 ctre

【问题讨论】:

  • 很可能是由于标准实现和/或粗心对每个目标架构的通用性和支持。尝试升级您的编译器或工具链可能会看到改进。
  • 假设std::regex 没有性能要求。 std::regex 的要求更多的是正确操作而不是速度。
  • 任何带有 (?i) 的东西都会失败,因为它不是扩展 posix 语法的一部分。我不确定{Sm}。您应该查看在构造正则表达式对象期间引发的异常,它可以为您提供更多信息。
  • std::regex 没有性能要求,所以一切正常。如果您想要稳定的性能,请使用 pcre2 之类的东西。
  • 另一种可能性是它针对其他用例进行了优化。您可以使用 DFA 或 NFA 解析正则表达式,构建 DFA 需要更多时间,但是使用 DFA 可以显着加快正则表达式的解析速度。您应该尝试将这种特殊情况作为附加测试用例。

标签: c++ regex benchmarking libstdc++ re2


【解决方案1】:

这是因为 C++ 标准要求,还是只是特定的实现没有得到很好的优化?

答案是肯定的。有点。

毫无疑问,libstdc++ 对<regex> 的实现没有得到很好的优化。但不止于此。并不是标准要求抑制了优化,而是标准要求抑制了更改

正则表达式库是通过一堆模板定义的。这允许人们在charwchar_t 之间进行选择,这在理论上是好的。但有一个问题。

通过将代码直接复制并粘贴到针对这些库编译的代码中来使用模板库。由于模板是如何被包含的,即使是模板库之外没有人知道的类型实际上也是库的 ABI 的一部分。如果更改它们,则针对不同版本的标准库编译的两个库将无法相互使用。而且因为正则表达式的模板参数是它的字符类型,所以这些实现细节基本上涉及到关于实现的一切

当 libstdc++(和其他标准库实现)开始发布 C++ 正则表达式的实现时,它们将自己绑定到一个特定的实现,该实现无法以影响库的 ABI 的方式进行更改。虽然它们可能会导致另一个 ABI 中断来修复它,但标准库实施者不喜欢破坏 ABI,因为人们不会升级到破坏其代码的标准库。

当 C++11 禁止 basic_string 写入时复制实现时,libstdc++ 出现了 ABI 问题。他们的 COW 字符串被广泛使用,更改它会使针对新字符串编译的代码在与针对旧字符串编译的代码一起使用时中断。在 libstdc++ 咬紧牙关并实际实现 C++11 字符串之前花了

如果 Regex 是在没有模板的情况下定义的,则实现可以使用传统机制来隐藏实现细节。外部代码接口的 ABI 可以是固定不变的,只有 ABI 背后的功能实现会随着版本的变化而变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2018-05-08
    • 2014-01-21
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多