一个基于 DFA 的正则表达式库,可编译为 JVM 字节码

多年前,Kragen 抱怨 Java 正则表达式的实现和性能,并建议实现一个能生成 JVM 字节码的版本可能会表现更好。如今,作者发布了 needle 的 0.0.1 版本,它能将正则表达式编译为 JVM 字节码,每个正则表达式被编译为确定性有限自动机(DFA),然后编译为 Java 类,代码会分析 DFA 以提取信息以更高效匹配,能检测可通过String.indexOf找到的前缀、后缀和中缀等。

基准测试

正则表达式性能难以简洁总结,needle 的设计使其更如此。例如一种优化会计算匹配的最小和最大长度,用于在不可能匹配时提前退出。在测试整个字符串匹配正则表达式或在足够小的字符串中搜索时会有效果,但在大字符串中找子串时不会。作者写了很多基准测试覆盖多种情况,但需编写代码来重复报告和比较结果,同时包含了一个特定基准(SherlockBenchmark)的部分结果。

对于每个正则表达式,在 Project Gutenberg 版《福尔摩斯历险记》中搜索所有匹配模式。比较 Java 标准库、Needle 和brics automaton 库,它是高效的 DFA 实现。测试中有三类模式:

  • 字面量:无重复或元字符,可通过String.indexOf找到,Needle 识别字面量并包含String.indexOf调用,标准库仍较慢但表现不错。如Sherlock等。
  • 子串/初始字符搜索:不是字面量,但有字面组件可通过String.indexOf缩小搜索空间,如[Ss]herlock等。
  • 其他所有:没有可通过String.indexOf搜索的子串,完全由自动机匹配,如Sherlock|Holmes等,Needle 比标准库快但比 brics 慢,因为 needle 自动机核心循环较慢,有可搜索子串时正则表达式性能受搜索子串速度主导,自动机速度不那么重要。

这里有两件事可做:一是扩展快速循环搜索正则表达式初始字符的情况;二是对于不能使用快速初始循环的剩余正则表达式,要改变生成代码以匹配或超过 brics 的性能。

阅读 14
0 条评论