保存/序列化提升或标准正则表达式
Save/Serialize boost or std regexes
是否可以序列化/反序列化和保存/加载正则表达式到文件/从文件加载?
我们有一个非常耗时的过程来构建一些正则表达式,我想知道我们是否可以通过保存和加载它们来节省一些时间。
不,这可能是不可能的,因为它无论如何都需要您重新编译正则表达式。
但是,如果使用 boost::xpressive,则可以在编译时通过正则表达式的表达式模板构造来编译正则表达式。这将使正则表达式编译时间完全消失。
提升压抑
但是,使用过多时间的真正原因几乎可以肯定是您通过使用回溯正则表达式引擎不正确地使用正则表达式,即 IE。
RE2 是一个传统的自动机正则表达式引擎,它不使用回溯,而是直接构造 NFA 或 DFA。如果您不使用反向引用或许多基于非正则表达式的"特征",则在许多极端情况下,使用 RE2 的速度将提高一个数量级。
如果您正在使用这些功能,您应该意识到它们将严格控制您的匹配速度,并且几乎可以肯定它们是您试图消除的速度变慢的主要原因。
这很难用 boost/stl 正则表达式类来实现。 问题是所述类的内部结构。
- 实现如何存储类属性?按地址、值?
- 编译器引入了哪些附加填充(如果有)?
- 是否存在任何平台对齐问题?
- 等。。。
以帮助说明问题的难度。 尝试查找C++类实例的大小。
regex pattern( "^Corvusoft$" );
printf( "%lun", sizeof( pattern ) ); //32
regex alternative( "C" );
printf( "%lun", sizeof( alternative ) ); //32
替代解决方案 1
在构建时创建包含所需正则表达式和链接的库,或通过 dlopen API 动态打开和加载库。 然后,您将使用诸如prelink之类的工具来确保它们已经在内存中;预编译。
替代解决方案 2
使用 C 正则表达式.h。
您可以遍历 regex_t POD 结构并将其内容写入二进制或内存映射文件。 稍后,您可以将这些数据值映射回新的regex_t结构,完全避免重新编译正则表达式。
#include <regex.h>
regex_t pattern;
int result = 0;
result = regcomp( &pattern, "^Corvusoft$", 0 );
if ( result )
{
fprintf( stderr, "Failed to compile regular expression patternn" );
}
TODO: walk structure and write to binary/memory mapped file.
替代解决方案 3
遵循@Alice的建议并使用Boost.Xpressive。
你可以序列化一个 boost::regex:
#include <string>
#include <iostream>
#include <sstream>
#include <boost/regex.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
namespace boost
{
namespace serialization
{
template<class Archive, class charT, class traits>
inline void save(Archive & ar,
const boost::basic_regex<charT, traits> & t,
const unsigned int /* file_version */)
{
std::basic_string<charT> str = t.str();
typename boost::basic_regex<charT, traits>::flag_type flags = t.flags();
// typename boost::basic_regex<charT, traits>::locale_type loc = t.getloc();
ar & str;
ar & flags;
// ar & loc;
}
template<class Archive, class charT, class traits>
inline void load(Archive & ar,
boost::basic_regex<charT, traits> & t,
const unsigned int /* file_version */)
{
std::basic_string<charT> str;
typename boost::basic_regex<charT, traits>::flag_type flags;
// typename boost::basic_regex<charT, traits>::locale_type loc;
ar & str;
ar & flags;
// ar & loc;
t.assign(str, flags);
// t.imbue(loc);
}
template<class Archive, class charT, class traits>
inline void serialize(Archive & ar,
boost::basic_regex<charT, traits> & t,
const unsigned int file_version)
{
boost::serialization::split_free(ar, t, file_version);
}
}
}
int main(int argc, char ** argv)
{
std::stringstream os;
{
boost::regex re("<a\s+href="([\-:\w\d\.\/]+)">");
boost::archive::text_oarchive oar(os);
oar & re;
}
os.seekg(std::ios_base::beg);
boost::regex re;
boost::cmatch matches;
boost::archive::text_iarchive iar(os);
iar & re;
boost::regex_search("<a href="https://stackoverflow.com/questions/18752807/save-serialize-boost-or-std-regexes">example</a>", matches, re);
std::cout << matches[1] << std::endl;
}
但这并不意味着与从字符串重建正则表达式相比,您将获得任何性能提升。
注意:为了简单起见,我省略了 std::locale 的东西
- 使用正则表达式regex_search在字符串中查找字符串
- 在 C++ 中使用正则表达式错误时出现问题 括号表达式中的范围无效
- C++正则表达式无限循环
- FindPackageHandleStandardArgs.cmake:137 的 CMake 错误(消息):找不到 Boost (缺少:正则表达式)(找到合适的版本"1.72.0",
- 定义有趣的宏和正则表达式在Z3 C++绑定
- 带有多个字符分隔符的正则表达式
- C++ 使用增强正则表达式库时断言崩溃
- 有人可以帮助我处理正则表达式吗?
- 使用正则表达式获取大括号块的列表
- 正则表达式以匹配数字的重复模式,后跟任何类型的分隔符?
- 组合正则表达式部分使用 | 不起作用的 C++
- 为什么C++正则表达式这么慢?
- 如何使HTML5电子邮件验证正则表达式在C++中工作?
- 标准库中的任何正则表达式语法是否支持 (?(定义)用于子模式参考?
- C++ 增强正则表达式与标准库正则表达式匹配结果
- 如何对标准::正则表达式进行哈希处理
- 巨大的程序大小C++与标准::正则表达式
- 为什么C++标准使正则表达式算法成为免费函数
- 保存/序列化提升或标准正则表达式
- 标准::C++正则表达式中有最大组限制吗?