diff --git a/README.md b/README.md index c734488e74ff4f6e7df86002c68e6b867d5713f3..dbe91f11ccce0bf6c44c787281ed5b31db4fa18a 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,19 @@ # re2-rust -a compatible RE2 API( -2021-11-01) by calling Rust library [regex](https://github.com/rust-lang/regex) +## re2-rust介绍 +re2-rust是来兼容RE2 API[(version 2021-11-01)](https://github.com/google/re2/tree/2021-11-01)的项目,通过调用[Rust正则表达式库](https://github.com/rust-lang/regex)进行实现。re2-rust的功能与原本RE2基本保持一致。 +re2-rust保留了re2中的对外的接口,分别在re2.h、set.h和filtered_re2.h中。 +re2.h中的接口可以实现正则表达式的匹配、查找和替换的功能;set.h中的接口可以同时处理多组正则表达式;filtered_re.h中的接口提供了一种预过滤机制,有助于减少需要实际搜索的regexp的数量。这些接口再调用Rust正则库中提供的接口对用户传递过来的数据进行处理,最后再把结果进行返回。 + + +## 编译、安装re2-rust ``` Shell $ git clone https://gitee.com/openeuler/re2-rust.git $ cd re2-rust ``` - -### 编译、安装re2-rust - -使用openEuler 22.03-LTS +**使用openEuler 22.03-LTS** ``` Shell dnf install git @@ -27,7 +29,7 @@ g++ testinstall.cc -o testinstall -lre2 ./testinstall ``` -Ubuntu 20.04 +**使用Ubuntu 20.04** ``` Shell $ make @@ -37,8 +39,543 @@ $ g++ testinstall.cc -o testinstall -lre2 $ ./testinstall ``` -## Test Rusults +## 性能测试 +RE2-Rust项目中只需要对re2目录下filtered_re2.h、re2.h、set.h文件中声明的部分函数进行性能测试,而filtered_re2.h中的主要函数是通过调用re2.h中的PartialMatch()函数实现的,所以下面只对re2.h和set.h文件中主要函数进行性能测试。相关的性能测试代码详见regexp_benchmark.cc文件。 +re2.h文件中相关函数的性能测试: +我们对re2.h对外接口中的FullMatch()、PartialMatch()、FindAndConsume()三个函数进行了测试,下面表格中的re2-c++和re2-rust分别通过上述三个函数测试了表格中的八个正则表达式,但由于这三个函数的本质是调用了RE2::DoMatch()函数,所以在表格中不对上面三个函数进行区分。下面表格是regexp_benchmark.cc中一些正则表达式在text_re2_1KB.txt文本下的执行时间。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

正则表达式

+

(含义)

+
+

RE2-C++

+
+

RE2-Rust

+
+

PCRE

+
+

Regex

+
+

“”

+

+
+

339 ns/iter

+
+

213 ns/iter

+
+

133 ns/iter

+
+

54 ns/iter

+
+

3019.80 MB/s

+
+

4785.82 MB/s

+
+

7653.53 MB/s

+
+

18890.09 MB/s

+
+

"abcdefg"

+

匹配abcdefg字符串

+
+

820 ns/iter

+
+

259 ns/iter

+
+

1686 ns/iter

+
+

97 ns/iter

+
+

1248.70 MB/s

+
+

3951.78 MB/s

+
+

607.26 MB/s

+
+

10507.00 MB/s

+
+

"(?-s)^(?:GET|POST) +([^ ]+) + HTTP"

+

匹配HTTP请求报文格式

+
+

343 ns/iter

+
+

246 ns/iter

+
+

147 ns/iter

+
+

92 ns/iter

+
+

2982.79 MB/s

+
+

4157.21 MB/s

+
+

6932.47 MB/s

+
+

11096.98 MB/s

+
+

"(?-s)^(.+)"

+

匹配行首连续出现一次以上的字符

+
+

542 ns/iter

+
+

212 ns/iter

+
+

203 ns/iter

+
+

56 ns/iter

+
+

1886.72 MB/s

+
+

4807.80 MB/s

+
+

5031.92 MB/s

+
+

18062.85 MB/s

+
+

"(?-s)^([ -~]+)")

+

匹配行首连续出现一次以上的ASCII字符

+
+

557 ns/iter

+
+

217 ns/iter

+
+

190 ns/iter

+
+

59 ns/iter

+
+

1835.28 MB/s

+
+

4715.87 MB/s

+
+

5365.38 MB/s

+
+

17188.64 MB/s

+
+

"(?s).*"

+

匹配任意字符

+
+

349 ns/iter

+
+

21223 ns/iter

+
+

154 ns/iter

+
+

2588 ns/iter

+
+

2929.63 MB/s

+
+

48.25 MB/s

+
+

6640.02 MB/s

+
+

395.62 MB/s

+
+

"(?s).*$"

+

匹配任意字符

+
+

11401 ns/iter

+
+

19678 ns/iter

+
+

159 ns/iter

+
+

2468 ns/iter

+
+

89.81 MB/s

+
+

52.04 MB/s

+
+

6415.22 MB/s

+
+

414.86 MB/s

+
+

"(?s)((.*)()()($))"

+

匹配任意字符

+
+

11179 ns/iter

+
+

19873 ns/iter

+
+

260 ns/iter

+
+

2488 ns/iter

+
+

91.59 MB/s

+
+

51.53 MB/s

+
+

3937.18 MB/s

+
+

411.54 MB/s

+
+注:(?s)表示单行模式 + +set.h文件中相关函数的性能测试: + +可以看到,set.h中主要是下面的函数接口有匹配功能: +bool Match(const StringPiece& text, std::vector* v) const; + +上述函数功能为同一文本可同时匹配多个正则表达式,并将匹配到的结果保存到向量v中,若传入的v为空则表示不需要返回匹配结果。 + +我们使用的待匹配文本还是text_re2_1KB.txt中的数据,同时匹配五个正则表达式,分别是"(?s).*"、"(?s).*$"、"(?s)((.*)()()($))"、"hwx"、"ldi"。 + +由于对于锚点为RE2::UNANCHORED、RE2::ANCHOR_BOTH、RE2::ANCHOR_START三种不同情况已经在RE2::Set::Add()已经进行了处理,所以对锚点三种不同情况的处理并不计算在匹配时间。为方便RE2-Rust与RE2-C++、Regex进行性能对比分析,我们采用锚点为RE2::UNANCHORED进行性能对比,详细性能评测代码见regexp_benchmark.cc文件中Set_Match_UNANCHORED_RE2()和Set_Match_UNANCHORED_NULL_RE2()函数。下面是set.h文件中RE2::Set::Match()在RE2-C++、RE2-Rust、Regex三种不同正则表达式框架下的性能对比结果(PCRE不支持同时匹配多个正则表达式): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

 

+
+

RE2-C++

+
+

RE2-Rust

+
+

Regex

+
+

V为空

+
+

1716 ns/iter

+
+

383 ns/iter

+
+

18 ns/iter

+
+

596.67 MB/s

+
+

2671.52 MB/s

+
+

56944 MB/s

+
+

V不为空

+
+

8231 ns/iter

+
+

535 ns/iter

+
+

6686 ns/iter

+
+

124.40 MB/s

+
+

1910.52 MB/s

+
+

153 MB/s

+
+ + +另外我们采用第三方正则表达式测试框架regex-performance,通过一些指定的正则表达式,对主流的正则表达式库进行了评测(测试详情可见https://gitee.com/openeuler/re2-rust/blob/master/test-results.txt),得到了如下结果: ``` Total Results: [ ctre] time: 4010462.7 ms, score: 6 points, @@ -56,11 +593,14 @@ Total Results: [rust_regex] time: 4790.2 ms, score: 56 points, [rust_regrs] time: 47772.1 ms, score: 6 points, ``` -从测试结果看re2-rust评分比re2略高,但是耗时re2-rust比re2增加很多,通过仔细分析发现正则表达式'[a-q][^u-z]{13}x'耗时特别高4280.7 - 130.5 = 4150.2 ms,另外'\b\w+nn\b'耗时322.6 - 23.9 = 298.7,除去这两个异常测试项外的16个测试项耗时re2-rust:334.4 ms vs. re2: 362 ms ,也就是说re2-rust在大多数情况下性能比re2要好。 - +从以上测试结果看re2-rust评分比re2略高,但是耗时re2-rust比re2增加很多,通过仔细分析发现正则表达式'[a-q][^u-z]{13}x'耗时特别高4280.7 - 130.5 = 4150.2 ms,另外'\b\w+nn\b'耗时322.6 - 23.9 = 298.7,除去这两个异常测试项外的16个测试项耗时re2-rust:334.4 ms vs. re2: 362 ms ,也就是说re2-rust在大多数情况下性能比re2要好。 从测试耗时看re2-rust和rust_regex两者相差3%(多次测评结果看两者差距上下浮动5%以内),总体看re2-rust和rust_regex性能基本一致。 +综合对比可知: +1. RE2-Rust在大部分测试用例下性能优于RE2-C++,而在涉及到捕获组会差于RE2-C++,原因可见https://github.com/rust-lang/regex/discussions/903 +2. RE2-rust和Regex性能大致相当,但是由于RE2-Rust是调用了Regex的对外的C接口,所以RE2-rust会比Regex多了函数调用开销、特殊处理、错误判断等开销,故RE2-Rust性能会略低于Regex +3. RE2-Rust支持多行模式,但不支持同名的捕获组 +4. RE2-Rust比RE2-C++支持更少的转义字符,比如”\C” -测试采用第三方正则表达式测试框架regex-performance,测试详情见test-results.txt # Links