繁体   English   中英

正则表达式性能的最佳实践VS纯粹的迭代

[英]Best practices for regex performance VS sheer iteration

我想知道是否有任何关于何时使用regex VS "string".contains("anotherString")和/或其他String API调用的一般指导原则?

虽然上面给出了.contains()决定是微不足道的(如果你能在一次调用中做到这一点,为什么还要使用正则表达式),现实生活带来了更复杂的选择。 例如,做两个.contains()调用还是单个正则表达式更好?

我的经验法则是始终使用正则表达式,除非可以用单个API调用替换它。 这可以防止代码膨胀,但从代码可读性的角度来看可能不是那么好,特别是如果正则表达式趋于变大。

另一个经常被忽视的论点是表现。 我怎么知道这个正则表达式需要多少次迭代(如“Big O”)? 它会比纯粹的迭代更快吗? 不知何故,每个人都认为,一旦正则表达式看起来短于5 if语句,它必须更快。 但情况总是这样吗? 如果无法事先预编译正则表达式,这尤其重要。

在不使用分析器的情况下很难估计性能,通常最好的策略是编写最具逻辑意义且更易于理解/阅读的内容。 如果两个.contains()调用更容易在逻辑上理解,那么这是更好的路径,如果正则表达式更有意义,则应用相同的逻辑。

考虑到团队中的其他开发人员可能对正则表达式没有很好的理解也很重要。 如果在生产的后期,使用正则表达式而不是.contains()(反之亦然)被认为是瓶颈,请尝试并分析两者。

经验法则:将代码编写为可读,使用分析器识别瓶颈,然后用更快的代码替换可读代码。

RegexBuddy有一个内置的正则表达式调试器。 它显示了正则表达式引擎找到匹配或找不到匹配所需的步数。 通过在不同长度的字符串上使用调试器,您可以了解正则表达式的复杂性(大O)。 如果您在RegexBuddy的帮助文件索引中查找“基准”,您将获得有关如何解释此问题的更多提示。

在判断正则表达式的性能时,测试正则表达式无法找到匹配项的情况尤为重要。 编写一个在线性时间内找到匹配的正则表达式非常容易,但在我称之为灾难性回溯的情况下,在指数时间内失败。

要使用5 if语句作为示例,正则表达式one|two|three|four|five一次扫描输入字符串,在遇到otf时执行一些额外的工作。 但是5 if语句检查字符串是否包含单词将在整个字符串中搜索5次,如果找不到任何单词。 如果在字符串的开头出现five ,那么正则表达式立即找到匹配,而前面的4个if语句在第五个if语句找到匹配之前徒劳地扫描整个字符串。

我强烈建议您为两者编写代码并将其计时。 这样做很简单,你会得到一个不是通用的“经验法则”的答案,而是一个非常具体的答案,适用于你的问题领域。

Vance Morrison有一篇关于微基准测试的优秀文章,并且有一个工具可以让你很轻松地回答这样的问题......

http://msdn.microsoft.com/en-us/magazine/cc500596.aspx

如果你想要我个人的“经验法则”那么RegEx对于这类事情来说往往比较慢,但是你应该忽略我并自己测量它:-)

如果,出于非性能原因,您继续使用正则表达式,那么我真的可以推荐两件事。 获取一个分析器(例如ANTS)并查看代码在生产中的作用。 然后,获取正则表达手册的副本......

http://www.amazon.co.uk/Regular-Expressions-Cookbook-Jan-Goyvaerts/dp/0596520689/ref=sr_1_1?ie=UTF8&s=books&qid=1259147763&sr=8-1

...因为它有很多关于加速RegEx代码的技巧。 我按照本书的提示将RegEx代码优化了10倍。

答案(像往常一样)取决于它。

在你的特殊情况下,我想替代方法是做正则表达式“this | that”,然后进行查找。 这个特殊的结构真的戳了正则表达式的弱点。 在这种情况下,“OR”并不真正知道子模式正在尝试做什么,因此无法轻松优化。 它最终做了(在伪代码中)相当于:

for( i = 0; i < stringLength; i++ ) {
    if( stringAt pos i starts with "this" )
       found!
    if( stringAt pos i starts with "that" )
       found!
}

几乎没有一种更慢的方法。 在这种情况下,两个contains()调用会快得多。

另一方面,完全匹配: ".*this.*|.*that.*"可以更好地优化。

对我来说,当其他方面的代码复杂或笨拙时,应该使用正则表达式。 因此,如果您想在目标字符串中找到两个或三个字符串中的一个,那么只需使用contains。 但是如果你想找到以'A'或'B'开头并以'g'结尾的单词 - 'm'...然后使用正则表达式。

然后你不会在这里和那里担心几个周期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM