【hyperscan】hyperscan开源了!

hyperscan开源了!正则表达式

官网:https://01.org/zh/hyperscan数据库

1. 新闻背景

    当地时间10月19日,intel将它的高速正则表达式匹配引擎hyperscan开源了,版本4.0,基于BSD许可。这个基于自动机(Automata)的引擎通过了多年开发(2008年起),通过不断优化与完善,效率很是之高,虽然没有pcre等对正则语法支持全面,但很是适用于网络设备。用户能够在网络设备数据面(Data Plane)使用hyperscan进行规则匹配,实现高性能DPI/lPS/IDS等应用。以前开源的dpdk,搭配hyperscan,简直是双剑合璧。express

    今后以后,DPI/IPS/IDS/NGFW开发人员能够把精力更多地放在业务上,而不须要苦于优化报文转发(dpdk之功)和规则匹配(hyperscan之力)的性能。对于DPI来讲,今后以后,也许特征/规则才是核心价值,软件自己已经不重要了。而基于dpdk的软件产品,凭借其不输太多的性能、较低的成本、较低的开发门槛和灵活性,也对相同功能的硬件产品发起了挑战。网络

2. 技术细节

    hyperscan的实现基于自动机(automata,  如NFA/DFA)而不是回溯(back-tracking)。这么作有好有坏。好处是能够支持流模式(streaming)和多模正则表达式;坏处是,基于自动机的正则匹配没法很容易地处理某些正则构造 -  backreferences and arbitrary lookaround asserts(好吧,我也不知道这俩到底啥意思)是不支持的两个主要特性。函数

    hyperscan所使用的一些技术包括:布局

Discovery of literal (fixed string) factors and decomposition of regular expressions into smaller chunks (which we call "engines") separated by these literal factors.
  These engines can be of many different types:
    Deterministic Finite Automata (DFA)
    Bit-parallel Glushkov Non-deterministic Finite Automata (NFA) engines
    Custom engines for special cases (such as large bounded repeats).
      These engines can take many different roles:
        "Prefix" engines that precede our literal factors
        "Suffix" engines that follow our literal factors
        "Infix" engines that lie between two literal factors
        "Outfix" engines that aren’t connected at all with literal factors (when no satisfactory factors can be found in a regular expression)
      These engines can often run lazily or not at all to reduce overhead.
  We merge smaller DFA/NFA engines into larger ones, where this can be done without performance loss.
  SIMD "acceleration" of automata based scanning: where we can substitute relatively simple SIMD tests of our input for complex automata execution, we do it.
  We use Intel SIMD instructions to handle larger-scale NFA and literal matching tasks: having 128 or 256 (or more) bits for a bit-parallel automaton is often helpful.
  ... and many more short-cuts to attempt to avoid doing expensive automata calculations that we ultimately won’t need.

 hyperscan设计目标:性能

  • 高性能,包括正常应用场景和边界条件下
  • 较小的database(正则表达式编译后造成的数据)
  • 运行于流模式时,较小的流状态数据(stream state) 。这种模式下每条流都要维护本身的流状态。

另外,还有一些设计要求或限制:优化

  • 运行库必须以C实现,由于一些数据面环境不支持C++
  • 不能够在运行时任意请求内存,用到的内存仅包括database、匹配临时数据(scratch)和流状态(在流模式下)。
  • database必须是平面化(flat)的内存布局,以即可以序列化/反序列化,或者能够内存中的一处移动到另外一处(这意味着内部不能含有指针)

3. API介绍

    hyperscan以C++实现,使用了boost库和C++11特性,但它的API却以简洁的C形式提供。hyperscan API主要分为两个部分:编译与匹配 (compile & scan)。用户提供的多个正则表达式先要通过编译,生成database,而后才能够调用匹配接口,使用此database进行匹配。this

    编译就是将多个正则表达式编译为hyperscan database,调用编译接口时能够传入一些flags和mode等参数,控制匹配行为和运行模式。hyperscan的运行模式主要有3个:BLOCK、STREAM和VECTORED。BLOCK模式就是对多个数据块分别进行匹配;STREAM模式将特定的一组数据库视为一个STREAM,为每个STREAM维护状态信息,它能够跨数据块进行匹配;VECTORED模式能够一次匹配多个数据块。使用不一样模式参数编译的database在匹配时不能混用。spa

    hyperscan的database能够序列化成文件(固然也能够反序列化),也能够在不一样机器间进行传递。

    编译的API主要有

hs_compile()
hs_compile_multi()
hs_compile_ext_multi()

   匹配就是基于编译好的database,对数据进行匹配,并获得匹配结果。 hyperscan在进行匹配时须要有一个临时数据(scratch),这块数据须要在数据面运行前就分配(不在运行时分配和释放,保证性能),且须要保证同一时刻仅有一个匹配过程在使用同一块临时数据。若是使用流模式,还须要预先为每一个流分配流状态数据。

    匹配结果是经过用户自定义的回调函数获取的。匹配过程当中只要发生命中,就会调用此函数。此函数返回0表示继续匹配,非0表示中止匹配。此函数的原型由hyperscan约定,用户经过实参,能够得到命中正则表达式对应的ID、匹配位置等信息。

    匹配回调函数的原型:

typedef (* match_event_handler)(unsigned int id, 
                                unsigned long long from, 
                                unsigned long long to, 
                                unsigned int flags, 
                                void *context)

    匹配的API主要有

hs_scan()
hs_scan_vector()
hs_scan_stream()

流模式的匹配较为复杂,这里不说起,下文有相关示例解读。

相关文章
相关标签/搜索