我们正在尝试摆脱 boost::regex ,但它的性能很糟糕。 根据 this 基准,Oniguruma 是整体上最好的。
我们有多个正则表达式(并且总是在变化),我们将其应用于从中型(100 个字符)到大型(1k 个字符)的字符串......所以这是一个非常异构的环境。
有人用过成功吗?您建议使用更“标准”的 PCRE 或 RE2 吗?
谢谢!
两种实现(FSA 和 BT)具有完全不同的行为,您可以在右侧栏(电子邮件)中看到。
oniguruma 通常很快,但如果您对特定的正则表达式“不幸”,则可能会运行缓慢。 那是因为它是一个回溯算法。
相比之下,虽然 re2 通常要慢一些,但它没有相同的风险 - 它的时间永远不会[*]以同样的方式爆炸(它没有最坏情况下的指数行为)。
所以这取决于细节。 如果您确信您的正则表达式是安全的,或者愿意检测并中止缓慢的匹配,那么 oniguruma 是有意义的。 但就我个人而言,我倾向于为 re2 的安全性多付一点(不多)。
有关此内容的更多信息,请参阅 http://swtch.com/~rsc/regexp/regexp1.html(由 re2 作者提供)。
[*] 好吧,也许永远都不会太强烈。 对于某些正则表达式,我认为在某些情况下必须依靠 BT 方法(可能涉及匹配之前的匹配和前瞻)。 但在大多数正则表达式上它仍然更安全。
我已经对以下库进行了基准测试:
基准测试包括执行一系列测试,这些测试在very异构正则表达式上大量使用正则表达式(分组、不分组、长(484个字符)、短、管道、?、*、.等)。适用于从几个字符到大约 8k 个字符的文本。
每次计算正则表达式匹配时,我都会存储正则表达式并递增毫秒计数器,以累积计算正则表达式所花费的时间(多次调用)。
这是每个库的所有正则表达式花费的总时间:
*我们(几乎)总是想捕获正则表达式中组的内容,而 re2 在捕获组时执行可怕(参见此处)。您在上面的结果中看不到那么多,因为当无法捕获该组时,它表现良好。例如,在这个正则表达式上(执行了很多次):
^((?:https?://)?(?:[a-z0-9\-]{1,63}\.)+(?:[a-z0-9\-]{1,63}))(?:[^\?]*).*$
以下是每个库的结果:
看到 re2 从 5663 毫秒下降到 37 毫秒。
所以我的结论是,就我们的使用而言,Oniguruma 显然更优越。
但是如果你不需要捕获组,re2是一个更好的选择,因为我发现它的API更容易使用。