Python 测试代码
Python 虽然本身运行缓慢,但它的标准库并不慢,因此我选择它作为性能对比的基线:
import re
import time
import sys
def match_with_re(lines, compiled_re):
matches = 0
for line in lines:
if compiled_re.search(line):
matches += 1
return matches
def main():
filename = “test.data”
try: with open(filename, "r", encoding="utf-8") as f: lines = f.read().splitlines() except FileNotFoundError: print(f"无法打开文件: {filename}", file=sys.stderr) return print(f"文件读取完成。总行数: {len(lines)}\n") if not lines: return pattern = r'\"TSLA.*?\"' compiled_re = re.compile(pattern) iterations = 2 total_matches = 0 start_time = time.perf_counter() for _ in range(iterations): total_matches += match_with_re(lines, compiled_re) end_time = time.perf_counter() total_duration_secs = end_time - start_time total_duration_ms = total_duration_secs * 1000 avg_duration_ms = total_duration_ms / iterations print(f"[Python re 结果] -------") print(f"循环总次数: {iterations}") print(f"总耗时: {total_duration_ms:.2f} ms") print(f"单次扫描平均耗时: {avg_duration_ms:.4f} ms") print(f"累计匹配成功行数: {total_matches}")ifname== “main”:
main()
测试结果
尽管只运行了两轮,但每个函数匹配的次数都在 1000 万次以上,足够摊平统计差异了。
下面是测试结果:
实现 总耗时 单次扫描平均耗时
Go regexp 1.771614875 s 885.8074 ms
Go regexp2go 1m27.618973125 s 43809.4866 ms
Python re 2038.25 ms 1019.1254 ms
std::regex 20775.7 ms 10387.8 ms
PCRE2 4625.82 ms 2312.91 ms
PCRE2 JIT 238.041 ms 119.02 ms
实现 总耗时倍率 单次扫描平均耗时倍率
Go regexp 0.87× 0.87×
Go regexp2go 43.02× 42.99×
Python re 1.00× 1.00×
std::regex 10.19× 10.19×
PCRE2 2.27× 2.27×
PCRE2 JIT 0.12× 0.12×
从结果来看,regexp2go 是最慢的。这个工具号称比 Go 1.16 的标准库最多快 5 倍,要么是 Go 的标准库有了飞跃式提升,要么是它夸大宣传。
C++ 标准库的 regex 慢是众所周知的,不过没想到会比 Python 基线慢一个数量级,令人捧腹。不同的标准库实现之间性能也是天差地别,我选用了最快的 libstdc++;如果换成 LLVM 的 libc++,性能会回退到和 regexp2go 一桌。除了慢之外,标准库还有代码膨胀的问题,仅仅简单使用基础功能和一个不算复杂的模式,就产生了 200 KB 左右的编译产物。
令人意外的是,PCRE2 在未开启 JIT 时居然会比 Python 慢。这是因为对于非贪婪匹配,PCRE2 的引擎会比 Go 和 Python 做更多工作,最终导致速度变慢。
总结