文档说明
关键词
hyperscan介绍
块模式(Block Mode)
流模式(Streaming Mode)
向量模式(Vectored Mode)
hyperscan使用
运行环境
安装
主要接口详解
示例详解
知识点
相关资源
源码位置
接口介绍等
性能测试
本文介绍的hyperscan主要能帮你解决以下问题:
(1)在一个字符串(连续的内存单元)中高速查找是否有一个字符串集中的一个或多个字符串;
(2)在一个字符串(不连续的内存单元)中高速查找是否有一个字符串集中的一个或多个字符串;
(3)在一个持续的流中高速查找是否有一个字符串集中的一个或多个字符串;
典型的持续流,如:不断提交上来的网络数据包,字符串集中的字符串可能被分割在不同的数据包中。
hyperscan匹配速率:是pcre的数十倍,数据吞吐率能到>10Gbps,甚至能>100Gbps.
多模匹配、多模式匹配、单模匹配、单模式匹配、流式匹配、自动机、自动状态机、AC( Aho-Corasick)自动机、BM(Boyer-Moore)算法、正则匹配、正则表达式。
hyperscan是intel推出的一款高性能正则表达式引擎,基于X86平台以PCRE为原型而开发,支持PCRE的大部分语法,用c语言开发,提供一套 C API 。
跟pcre区别:
(1)hyperscan匹配速率是pcre的数十倍;
(2)hyperscan支持多模式匹配,不像pcre只支持单条的正则表达式的匹配。
hyperscan支持多种匹配模式:块模式、流模式、向量模式。
对一段完整的数据块进行扫描匹配,扫描匹配结束即返回最终结果,也即所有匹配的结果都在该段完整的数据块中,匹配结果不跨数据块,是一种传统的匹配模式。
块模式在所有模式中,消耗资源最小,匹配效率最高。
当扫描的结果不在一段完整的数据块中时,如在在真实网络场景下,数据是分散在持续不断过来的数据包中的,我们叫它数据流,扫描的结果往往会跨数据包,在不同的数据包中都有自己的一部分。这时要匹配到正确的结果,如果用传统的匹配思路,可以把所有数据全部缓存下来,最终来一次匹配。但是这样的话不仅会增加内存的开销,还会使得匹配没有了实时性,因为数据流可能会持续很长的一段时间。
Hyperscan的流模式,专门设计为对这种流数据的匹配。通过有限量的流内存对流匹配信息进行记录,在不缓存已过去流数据的情况下,保证能正确地匹配出所有结果,同时也不会有匹配不实时的问题。
向量模式适用以下场景:
(1)不是对一段完整的数据块进行扫描匹配,要扫描匹配的数据块分散在多个不连续的内存块中;
(2)这些不连续的数据,也不像流数据在时间上有到来的先后,而是在扫描前用户就能全部准备好。
hyperscan只能在x86平台上运行。
以下安装过程基于linux(centos)。
ragel安装
源码下载地址:
Ragel State Machine Compilerhttp://www.colm.net/open-source/ragel/
本次安装版本为:ragel-6.10.tar.gz
安装过程:
$ tar -xvf ragel-6.10.tar.gz //解压
$ cd ragel-6.10
$ ./configure
$ make
$ sudo make install
$ ldconfig // 让动态链接库为系统所共享
boost安装
源码下载地址:
Boost C++ Libraries - Browse /boost at SourceForge.netFree peer-reviewed portable C++ source librarieshttps://sourceforge.net/projects/boost/files/boost
本次安装版本为:boost_1_69_0
安装过程:
$ tar -xvf boost_1_69_0.tar.gz // 解压
$ cd boost_1_69_0
$ ./bootstrap.sh
$ sudo ./b2 --with-iostreams --with-random install // 只安装iostreams和random,当然也可以完整安装,安装过程会比较慢
$ ldconfig // 让动态链接库为系统所共享
源码下载地址:
Releases · intel/hyperscan · GitHubHigh-performance regular expression matching library - Releases · intel/hyperscanhttps://github.com/intel/hyperscan/releases
本次安装版本为:hyperscan-5.1.0
安装过程:
$ tar -xvf hyperscan-5.1.0.tar.gz
$ cd hyperscan-5.1.0
$ mkdir cmake-build
$ cd cmake-build
$ cmake -DBUILD_SHARED_LIBS=on -DCMAKE_BUILD_TYPE=Release ..
$ make -j8 // 多线程加速编译
$ sudo make install
$ ldconfig // 让动态链接库为系统所共享
从使用角度上介绍各匹配模式的主要接口,其他接口详见“相关资源”->“接口介绍等”。
(1)正则表达式编译函数
hs_error_t hs_compile(const char *expression, unsigned int flags, unsigned int mode, const hs_platform_info_t *platform, hs_database_t **db, hs_compile_error_t **error)
//单模正则匹配编译函数
expression:要被编译的正则表达式,也即搜索字符串集;
flags:表达式行为的标志,如:是否大小写敏感(HS_FLAG_CASELESS
)等,具体可参看hyperscan源码中的 hs_compile.h 文件;
mode:数据库匹配模式标志:
HS_MODE_BLOCK :块模式
HS_MODE_STREAM :流模式
HS_MODE_VECTORED :向量模式
platform:确定数据库的目标平台,一般写NULL,表示生成适合在当前主机平台上运行的数据库;
db:指向最终编译成的模式数据库指针;
error:错误返回,出错是,需用 hs_free_compile_error () 函数释放该缓冲区;
hs_error_t hs_compile_multi(const char *const *expressions, const unsigned int *flags, const unsigned int *ids, unsigned int elements, unsigned int mode, const hs_platform_info_t *platform, hs_database_t **db, hs_compile_error_t **error)
//多模正则匹配编译函数
expressions:指针数据,用于存储多个匹配表达式(pcre也是单模,一次只能编译一条正则表达式),不同于hs_compile函数的expression,是一个字符串指针;
(2)分配草稿空间
hs_error_t hs_alloc_scratch( const hs_database_t * db , hs_scratch_t ** scratch )
db:编译函数生成的数据库,如上面hs_compile生成的db;
scratch:指向草稿空间指针,用于返回分配的草稿空间;
(3)块扫描函数
hs_error_t hs_scan( const hs_database_t * db , const char * data , unsigned int length , unsigned int flags , hs_scratch_t * scratch , match_event_handler onEvent , void * context )
db:编译函数生成的数据库,如上面的hs_compile;
data:指向被扫描数据的指针;
length:被扫描数据的长度;
flags:预留,暂未使用;
scratch:数据库草稿空间,多线程检测时,每个检测线程都需要自己独立的草稿空间;
onEvent:匹配时间的回调函数,每触发一次匹配将调用一次改回调函数;
context:指向用户自定义数据,用于onEvent函数做响应的结果返回;
(4)释放草稿空间
hs_error_t hs_free_scratch(hs_scratch_t *scratch)
scratch:指向将被释放的草稿空间;
(5)释放编译数据库
hs_error_t hs_free_database(hs_database_t *db)
db:指向将被释放的模式数据库,如上面hs_compile生成的db;
主要流程参看,块模式,这里只列出之间的差异。
(1)正则表达式编译函数
(2)分配草稿空间
(3)打开数据流
hs_error_t hs_open_stream( const hs_database_t * db , unsigned int flags , hs_stream_t ** stream )
db:编译函数生成的数据库;
flags:预留,暂未使用;
stream:指向该函数生成的数据流;
(4)流扫描函数
hs_error_t hs_scan_stream( hs_stream_t * id , const char * data , unsigned int length , unsigned int flags , hs_scratch_t * scratch , match_event_handler onEvent , void * ctxt )
id :hs_open_stream 函数放回的数据流;
其他参数同块模式的块扫描函数。
(5)释放草稿空间
(6)关闭数据流
hs_error_t hs_close_stream( hs_stream_t * id , hs_scratch_t * scratch , match_event_handler onEvent , void * ctxt )
id:hs_open_stream 函数放回的数据流;
scratch:由 hs_alloc_scratch () 分配的草稿空间。仅当 onEvent 回调也是 NULL 时才允许为 NULL;
onEvent:指向匹配事件回调函数的指针。如果为 NULL 指针,则不会返回匹配结果;
ctxt:指向用户自定义数据,用于匹配发生时返回结果;
(7)释放编译的数据库
主要流程参看块模式,这里只列出之间的差异。
(1)正则表达式编译函数
(2)分配草稿空间
(3)向量扫描函数
hs_error_t hs_scan_vector( const hs_database_t * db , const char * const * data , const unsigned int * length , unsigned int count , unsigned int flags , hs_scratch_t * scratch , match_event_handler onEvent , void * context )
data:指针数组,指向要扫描数据;
length:对应指针数组,每个指针指向数据的大小;
count:data指针数组的大小,也即数组length的大小;
其他参数上面的其他接口函数。
(4)释放草稿空间
(5)释放编译的数据库
hyperscan源码的示例,位置:
examples/simplegrep.c
示例功能简介:
块模式匹配,运行参数argv[1]提供扫描串编译生成模式数据库,运行参数argv[2]为一个文件,文件内容为被扫描数据。
hyperscan源码的示例,位置:
examples/pcapscan.cc
示例功能简介:
通过读取pcap文件(pcap文件可通过一些网络工具,如wireshark捕获数据包生成的文件),模拟实际网络环境做流模式匹配。
(1)做多线程匹配时,每个线程都需要有自己独立的草稿空间,分别调用hs_clone_scratch 和hs_free_scratch做对应的克隆和释放;
(2)匹配结果,为效率考虑,只提供匹配结果在被匹配字符串结束位置(即to:相对于字符串开始的偏移位置),匹配的回调函数:
int match_event_handler(unsigned int id, unsigned long long from, unsigned long long to, unsigned int flags, void *context )
要想得到起始位置from,在编译模式数据库时,需在对应的表达式上加上flag标志:HS_FLAG_SOM_LEFTMOST。
(3)流式匹配要想获得匹配的起始位置from,除了(2)中加上对应的flag标志外,还需在编译时加上特定mode标志,即下三个中的一个:
/**
* Compiler mode flag: use full precision to track start of match offsets in
* stream state.
*
* This mode will use the most stream state per pattern, but will always return
* an accurate start of match offset regardless of how far back in the past it
* was found.
*
* One of the SOM_HORIZON modes must be selected to use the @ref
* HS_FLAG_SOM_LEFTMOST expression flag.
*/
#define HS_MODE_SOM_HORIZON_LARGE (1U << 24)
/**
* Compiler mode flag: use medium precision to track start of match offsets in
* stream state.
*
* This mode will use less stream state than @ref HS_MODE_SOM_HORIZON_LARGE and
* will limit start of match accuracy to offsets within 2^32 bytes of the
* end of match offset reported.
*
* One of the SOM_HORIZON modes must be selected to use the @ref
* HS_FLAG_SOM_LEFTMOST expression flag.
*/
#define HS_MODE_SOM_HORIZON_MEDIUM (1U << 25)
/**
* Compiler mode flag: use limited precision to track start of match offsets in
* stream state.
*
* This mode will use less stream state than @ref HS_MODE_SOM_HORIZON_LARGE and
* will limit start of match accuracy to offsets within 2^16 bytes of the
* end of match offset reported.
*
* One of the SOM_HORIZON modes must be selected to use the @ref
* HS_FLAG_SOM_LEFTMOST expression flag.
*/
#define HS_MODE_SOM_HORIZON_SMALL (1U << 26)
Releases · intel/hyperscan · GitHubHigh-performance regular expression matching library - Releases · intel/hyperscanhttps://github.com/intel/hyperscan/releases
http://intel.github.io/hyperscan/dev-reference/api_files.html#file-hs-h
hyperscan_sys - RustHyperscan is a software regular expression matching engine designed with high performance and flexibility in mind.https://docs.rs/hyperscan-sys/0.2.1/hyperscan_sys/
section2--hyperscan 的对应接口 - 高性能正则 - 计算机科学 | Echidna = Echidna 的小窝 = l am the bone of my swordhttp://www.echidna-sxh.com/hyperscan/hyperscan-api/
【ClickHouse为什么这么快?】3. 正则匹配算法 re 和 hyperscan 介绍_51CTO博客_clickhouse正则匹配查询【ClickHouse为什么这么快?】3. 正则匹配算法 re 和 hyperscan 介绍,一、什么是正则表达式?如何匹配特定的字符串?为了解决这个问题,定义一淘描述字符串特征的的模式,用于查找、替换符合特征的字符串,或者用来验证某个字符串是否符合指定的特征——这个模式就是“正则表达式”。正则表达式最初的想法源于1940年,神经生理学家WaarrenMcCulloch与WalterPitts研究出了一种用数而简单的自...https://blog.51cto.com/u_15236724/5365574