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

许多年前,Kragen抱怨 Java 正则表达式的实现和性能,并建议发出 JVM 字节码的实现可以表现更好。

今天,我发布了Needle的 0.0.1 版本,这是一个将正则表达式编译为 JVM 字节码的库。它将每个正则表达式编译为确定性有限自动机 (DFA),然后将其编译为 Java 类。

  • 代码会分析 DFA 以提取有助于更高效匹配的信息。
  • 它能检测出所需的前缀、后缀和前后缀,
  • 这些前缀、后缀和前后缀可以使用 String.indexOf 找到,而第一个字符则可以在 while 循环中轻松测试(例如 [Ss])。
  • 这使得该类在 DFA 自动机中花费的时间更少,而在快速循环中花费的时间更多。

基准 Regex 的性能不适合简明扼要的总结,而needle 的设计更是如此。例如,

  • 有一种优化会计算匹配的最小和最大长度,并在无法匹配时提前退出。在测试整个字符串是否与 regex 匹配时,或者在足够小的字符串中搜索时,这种效果就会显现出来,
  • 但在查找大字符串中的匹配子串时,这种效果就不会显现。

我已经编写了许多基准测试,涵盖了许多不同的情况,但需要编写代码来重复报告和比较结果。与此同时,我包含了一个特定基准测试 ( SherlockBenchmark ) 的结果。

对于每个正则表达式,我们搜索《福尔摩斯历险记》的古腾堡计划版本,找到该模式的所有匹配项。对于每个正则表达式,我们比较了 Java 标准库 Needle 和brics 自动机库,这是一个高效的 DFA 实现。

Needle 在这些模式上比 brics 慢,但仍然比标准库快得多。这是因为Needle 自动机的核心循环比brics 自动机慢。

当我们有一个可用的子字符串用于搜索时,正则表达式的性能由搜索该子字符串的速度决定,而自动机的速度则不太重要。但当没有子串时,brics 获胜。