与其他跨平台正则表达式库相比,Oniguruma 有多好?

Posted

技术标签:

【中文标题】与其他跨平台正则表达式库相比,Oniguruma 有多好?【英文标题】:How good is Oniguruma compared to other cross-platform regexp libraries? 【发布时间】:2012-08-16 23:44:02 【问题描述】:

我们正试图摆脱 boost::regex,它的性能很糟糕。 根据this 基准,Oniguruma 是最好的整体。

我们有多个正则表达式(并且总是在变化),我们将它们应用于从中等(100 个字符)到巨大(1k 个字符)的字符串......所以这是一个非常异构的环境。

你们中有人成功使用过它吗?您是否建议选择 PCRE 或 RE2 等更“标准”的?

谢谢!

【问题讨论】:

剖析,剖析,剖析...如果它是关键任务,您应该花时间测试不同的库以找到最适合您的库,当然同时进行剖析。 这就是我们一直在做的,我会尝试在这里发布基准测试的结果。 【参考方案1】:

这两种实现(FSA 和 BT)具有完全不同的行为,您可以在右侧的列(电子邮件)中看到。

oniguruma 通常很快,但如果您对特定的正则表达式“不走运”,则可能会运行缓慢。那是因为它是一种回溯算法。

相比之下,虽然 re2 通常会慢一些,但它没有相同的风险 - 它的时间永远不会[*] 以相同的方式爆炸(它没有最坏情况下的指数行为)。

所以这取决于细节。如果你确信你的正则表达式是安全的,或者愿意检测并中止慢匹配,那么 oniguruma 是有意义的。但我个人倾向于为 re2 的安全性支付更多(不多)。

有关更多信息,请参阅http://swtch.com/~rsc/regexp/regexp1.html(由 re2 作者提供)。

[*] 好吧,也许永远不会太强大。对于某些正则表达式,我认为在某些情况下它必须依靠 BT 方法(可能涉及匹配先前的匹配和前瞻)。但在大多数正则表达式上它仍然更安全。

【讨论】:

【参考方案2】:

我已经使用以下库进行了基准测试:

提升 re2 鬼鲛

基准测试包括执行一系列测试,这些测试大量使用了非常异构正则表达式(分组,不分组,长(484个字符),短,管道,\?, *, 。, ETC。)。应用于从几个字符到大约 8k 个字符的文本。

每次计算正则表达式匹配时,我都会存储正则表达式并递增一个毫秒计数器,以累积计算正则表达式所花费的时间(称为多次)。

这是每个库的所有正则表达式所花费的总时间:

提升:98840 毫秒 re2:51197 毫秒 小鬼:16095 毫秒 re2(无 CAPUTRE* 见下文)):16162 毫秒

*我们(几乎)总是希望在正则表达式中捕获组的内容,而 re2 在捕获组时执行可怕(see here)。在上面的结果中你看不到那么多,因为当组不能被捕获时,它表现得很好。例如在这个正则表达式上(执行了很多次):

^((?:https?://)?(?:[a-z0-9\-]1,63\.)+(?:[a-z0-9\-]1,63))(?:[^\?]*).*$

这是每个库的结果:

提升:140 毫秒 re2:5663 毫秒 鬼魂:53 毫秒 re2(无捕获):37 毫秒。

查看 re2 从 5663 毫秒到 37 毫秒的下降。

tl;博士

所以我的结论是,就我们的使用而言,Oniguruma 显然更胜一筹。

但如果您不需要捕获组,re2 是更好的选择,因为我发现它的 API 更易于使用。

【讨论】:

您是否重复使用了相同的正则表达式(即使用某种形式的正则表达式预编译)?另外,你有基准的链接吗? 嘿,抱歉,这是 2 年前的事了,我不再拥有用于基准测试的文件(或者更确切地说,我不知道它们在哪里 ^^)。我应该更好地记录这一点,因为我猜你使用库的方式会对性能产生巨大影响。下次会做得更好! 感谢您的更新 - 这有点远 :-)

以上是关于与其他跨平台正则表达式库相比,Oniguruma 有多好?的主要内容,如果未能解决你的问题,请参考以下文章

干货 | Logstash自定义正则表达式ETL实战

PHP 7.4.x中mbstring的正则表达式功能需要oniguruma。解决错误“No package 'oniguruma' found”。

Logstash:使用自定义正则表达式模式

[PHP] 解决no package ‘oniguruma’ found

QRegexp 特质(与 perl 相比):如何在没有惰性量词的情况下编写此正则表达式?

re库:Python中正则表达式的处理与应用