为什么 std::regex 比其他正则表达式库慢得多?
Why is std::regex notoriously much slower than other regular expression libraries?
This Github repository 将 std::regex 添加到正则表达式引擎列表中并被其他引擎淘汰。
为什么 std::regex - 在 libstdc++ 中实现 - 比其他的慢很多?这是因为 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 的比较。
更新 2:添加了 ctre
Is that because of the C++ standard requirements or it is just that that particular implementation is not very well optimized?
答案是肯定的。有点。
毫无疑问,libstdc++对<regex>
的实现没有优化好。但不仅如此。并不是说标准要求抑制了优化,而是标准要求抑制了 changes.
正则表达式库是通过一堆模板定义的。这让人们可以在char
和wchar_t
之间进行选择,这在理论上是好的。但是有一个问题。
模板库通过将代码直接复制并粘贴到针对这些库编译的代码中来使用。由于模板的包含方式,即使是模板库之外无人知晓的类型也实际上是库 ABI 的一部分。如果更改它们,针对不同版本的标准库编译的两个库将无法相互使用。而且因为正则表达式的模板参数是它的字符类型,所以这些实现细节基本上触及关于实现的一切。
分钟 libstdc++(和其他标准库实现)开始发布 C++ 正则表达式的实现,它们将自己绑定到一个特定的实现,不能以影响库 ABI 的方式进行更改。虽然他们可能会导致另一个 ABI 中断来修复它,但标准库实现者不喜欢破坏 ABI,因为人们不会升级到破坏他们代码的标准库。
当 C++11 禁止 basic_string
写时复制实现时,libstdc++ 出现了 ABI 问题。他们的 COW 字符串被广泛使用,更改它会使针对新字符串编译的代码在与针对旧字符串编译的代码一起使用时中断。在 libstdc++ 硬着头皮并实际实现 C++11 字符串之前花了 年。
如果 Regex 是在没有模板的情况下定义的,则实现可以使用传统机制来隐藏实现细节。用于外部代码接口的 ABI 可以是固定不变的,只有 ABI 背后的功能实现在不同版本之间发生变化。
This Github repository 将 std::regex 添加到正则表达式引擎列表中并被其他引擎淘汰。
为什么 std::regex - 在 libstdc++ 中实现 - 比其他的慢很多?这是因为 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 的比较。
更新 2:添加了 ctre
Is that because of the C++ standard requirements or it is just that that particular implementation is not very well optimized?
答案是肯定的。有点。
毫无疑问,libstdc++对<regex>
的实现没有优化好。但不仅如此。并不是说标准要求抑制了优化,而是标准要求抑制了 changes.
正则表达式库是通过一堆模板定义的。这让人们可以在char
和wchar_t
之间进行选择,这在理论上是好的。但是有一个问题。
模板库通过将代码直接复制并粘贴到针对这些库编译的代码中来使用。由于模板的包含方式,即使是模板库之外无人知晓的类型也实际上是库 ABI 的一部分。如果更改它们,针对不同版本的标准库编译的两个库将无法相互使用。而且因为正则表达式的模板参数是它的字符类型,所以这些实现细节基本上触及关于实现的一切。
分钟 libstdc++(和其他标准库实现)开始发布 C++ 正则表达式的实现,它们将自己绑定到一个特定的实现,不能以影响库 ABI 的方式进行更改。虽然他们可能会导致另一个 ABI 中断来修复它,但标准库实现者不喜欢破坏 ABI,因为人们不会升级到破坏他们代码的标准库。
当 C++11 禁止 basic_string
写时复制实现时,libstdc++ 出现了 ABI 问题。他们的 COW 字符串被广泛使用,更改它会使针对新字符串编译的代码在与针对旧字符串编译的代码一起使用时中断。在 libstdc++ 硬着头皮并实际实现 C++11 字符串之前花了 年。
如果 Regex 是在没有模板的情况下定义的,则实现可以使用传统机制来隐藏实现细节。用于外部代码接口的 ABI 可以是固定不变的,只有 ABI 背后的功能实现在不同版本之间发生变化。