hyperscan 作为和intel深度绑定的政策匹配工具,提供了及其弱小的正则匹配性能,并提供接口,不便对匹配后果进行二次操作。
我在学习hyperscan时,在各大论坛并没有找到比拟齐备并且具体解说,很多只是提到了函数库大略时干什么的,索性将本人理解到的货色,具体的记录下来,也算是本人对hyperscan的一次坚固
hyperscan 是英特尔开源的一款正则匹配工具,与intel芯片深度绑定,intel对其有专门的优化,因而在整体的匹配效率上,相较于其余正则计划,处于一个较为当先的地位。 hyperscan反对pcre 正则规定,现有的次要利用计划大都是基于pcre做的匹配。
样例代码放在了github上,前面会贴出来。
注: 本文演示环境为 ubuntu 22.04
hyperscan下载安装
- 下载
intel在github上凋谢了源码,通过git即可下载,因为github,在国内拜访不敌对,在gitee上也有相干开源代码
githubgit clone https://github.com/intel/hyperscan.gitgiteegit clone https://gitee.com/tzichengchew/hyperscan.git
- 依赖
hyperscan 应用cmake编译cmake等根底库装置不再赘述, 须要依赖 - boost
Boost Downloads
- ragel
Ragel State Machine Compiler (colm.net)
git clone https://github.com/adrian-thurston/ragel.git
* colm
git clone https://github.com/adrian-thurston/colm.git
其中ragel的装置须要clom反对在官网均能找到下载地址。或者git地址
- 装置
装置boost
bash bootstrap.sh && ./b2 && ./b2 install
装置ragel
不倡议编译装置,坑很多
sudo apt install ragel
编译装置hyperscan
创立一个目录
mkdir hyperscan_comp
执行编译命令
cmake $HYPERSCAN_PATHmake && make install
须要蛮久的。
遇到一个十分辣手的问题:
undefined reference to `avx2_memset'undefined reference to `corei7_memset'…………
https://github.com/intel/hyperscan/issues/292#issuecomment-762635447
亲测无效。
我在另外一台设施上测试发现并没有报错,预计可能是虚拟机cpu配置问题,后面提到了,hyperscan与intel深度绑定。
批改过cmake/build_wrapper.sh脚本后,就能够执行cmake命令了
为避免产生的cmake文件搞混了源文件,这里倡议建设一个新的目录,执行cmake
须要留神的是,在应用hyperscan时,动静库要比动态库应用绝对不便,批改CMakeCache.txt文件,依据版本不同,所在行数也不同。
BUILD_STATIC_AND_SHARED:BOOL=OFF->BUILD_STATIC_AND_SHARED:BOOL=ON
批改过后即可执行make && make install
hyperscan 简略应用
hyperscan整体的应用流程次要分为编译器和运行期
编译期
编译器次要是将编辑好的正则,编译成数据库供后续应用,
次要包含三个函数,别离实用不同的应用场景
- hs_compile() 将单个规定编译成数据库。
- hs_compile_multi() 将一组规定编译成数据库。
- hs_compile_ext_multi() 将一组规定编译成数据库,并反对扩大参数。
具体细节能够参考《深入浅出 Hyperscan: 高性能正则表达式算法原理与设计》
本例设计应用hs_compile_multi() 应该是最罕用的函数,普适性较高
定义宏,不便后续应用
enum { HYPERSCAN_ID_NONE = 0, HYPERSCAN_ID_TEST1, HYPERSCAN_ID_TEST2, HYPERSCAN_ID_MAX};
定义数据结构
/*** 将数据库中待编译的信息保留到这个数组外面*/typedef struct CompilePatternArray { uint32_t ids[20]; /**< id */ uint32_t flag[20]; /**< 编译参数 */ const char *exps[20]; /**< 正则 */} CompilePatternArray_t;/*** 编译数据结构*/typedef struct CompilePattern { uint32_t ids; const char *exps;} CompilePattern_t;
应用数组定义一组正则规定
/*** 编译到数据库中的匹配字段,* hyperscan编译阶段有一个特殊字符本义的过程*/static const CompilePattern_t gCompilePattern[] = { {HYPERSCAN_ID_NONE, " "}, {HYPERSCAN_ID_TEST1, "123.{1,3}abc"}, {HYPERSCAN_ID_TEST2, "max"}};
编译
/**** @param CompPatt* 待编译信息* @param count* 数据条数* @param pDatabase* 数据库* @return* 返回值,临时没定义*/static int CompilePatterns(CompilePattern_t *CompPatt, uint32_t count, hs_database_t **pDatabase) { hs_error_t error; hs_compile_error_t *ComError; CompilePatternArray_t compilePattern; // 一对一存储,转存 int i; for (i = 0; i < count; i++) { compilePattern.ids[i] = CompPatt[i].ids; compilePattern.exps[i] = CompPatt[i].exps; compilePattern.flag[i] = HS_FLAG_CASELESS; // 疏忽大小写 } // 编译 /** * 参数阐明 * 1. 正则 * 2. 正则匹配标签 * 3. id * 4. 数量 * 5. 匹配模式 * 6. platform 须要深刻去理解一下,目前置NULL * 7. 数据库指针 * 8. errorInfo */ error = hs_compile_multi(compilePattern.exps, compilePattern.flag, compilePattern.ids, count, HS_MODE_BLOCK, NULL, pDatabase, (hs_compile_error_t **) &ComError); if (error != HS_SUCCESS) { // 失败的话给出相应的提示信息 std::cout << "compile failed error code is " << error << std::endl; } return 0;}
运行期
hypersacn 运行过程中,进行正则匹配会有一个中间状态暂存匹配信息,须要创立一个scratch空间
hs_alloc_scratch(HsDatabase, (hs_scratch_t **) &HsStra);
运行期分为块模式,流模式,向量模式,块模式能够简略的了解为就一次数据输出,输入后果,流模式次要针对网络字节流,但相较于块模式,减少了流开启与敞开的过程,在编译期须要编译的内容也有所区别,本例中次要是块模式样例,流模式,有趣味能够自行钻研。
应用
hs_scan()进行匹配,调用时须要规定回调函数
/** 参数阐明* 1. 数据库* 2. 待匹配字符串* 3. 字符串长度* 4. flag, 未定义,官网阐明待用* 5. scratch* 6. 回调函数* 7. 回调函数传参*/hs_scan(HsDatabase, tmpString, strlen(tmpString), 0, HsStra, onMatch, tmpString);
回调函数
/** * 回调函数 * @param id * 匹配字段的 id * @param from * 从哪里还是匹配的 * @param to * 匹配到哪里完结(指向尾部) * @param flags * 基本没用, hyperscan 官网明确阐明没有应用的参数。 * @param ctx * 回调参数 * @return * 临时没用 */static int onMatch(unsigned int id, unsigned long long from, unsigned long long to, unsigned int flags, void *ctx) { char *tmp = (char *) ctx; std::cout << "id is " << id << std::endl; switch (id) { case HYPERSCAN_ID_NONE: std::cout << std::endl; break; case HYPERSCAN_ID_TEST1: std::cout << "form:" << tmp + from << std::endl; std::cout << "to:" << tmp + to << std::endl; std::cout << std::endl; break; case HYPERSCAN_ID_TEST2: std::cout << "form:" << tmp + from << std::endl; std::cout << "to:" << tmp + to << std::endl; std::cout << std::endl; break; default: std::cout << "can not found any subString" << std::endl; break; } return 0;}
传入字符串
abc123123123abcmax123123bacbacabc\0
执行成果
后记
hyperscan作为一个高性能正则匹配工具,利用场景很多,王翔学生等用几百页文字具体介绍了hyperscan基本原理,算法过程与高级个性,但真正应用还须要真正去实际能力真正了解,并且用好这个工具
残缺代码放在了gitee上,欢送大家补充,斧正。
https://gitee.com/wang-xiaotian-1/MyHyperscanTest.git