最有效的方法来检查$ string是否以$ per开头

时间:2015-07-30 13:00:24

标签: performance perl string-matching

$string中给出两个字符串变量$needleperl,检查$string是否以$needle开头的最有效方法是什么。

  • $string =~ /^\Q$needle\E/是我能想到的最接近的匹配,它可以满足要求,但是我尝试的解决方案效率最低(到目前为止)。
  • index($string, $needle) == 0有效且对$string$needle的某些值相对有效,但在其他位置不必要地搜索针头(如果在开始时未找到)。
  • substr($string, 0, length($needle)) eq $needle应该非常简单有效,但在我的几个测试中,大多数测试都不比前一个测试更有效。

perl中是否有规范的方法可以做到这一点,我不会意识到或以任何方式优化上述任何解决方案?

(在我的特定用例中,$string$needle在每次运行中都会有所不同,因此预编译regexp不是一种选择。)

如何衡量给定解决方案的性能的示例(此处来自POSIX sh):

string='somewhat not so longish string' needle='somew'
time perl -e '
  ($n,$string,$needle) = @ARGV;
  for ($i=0;$i<$n;$i++) {

    index($string, $needle) == 0

  }' 10000000 "$string" "$needle"

使用这些值,使用perl 5.14.2,index()使用此系统的效果优于substr()+eq,但使用:

string="aaaaabaaaaabaaaaabaaaaabaaaaabaaaaab" needle="aaaaaa"

那是相反的。

2 个答案:

答案 0 :(得分:20)

这有多重要,真的吗?我做了很多基准测试,index方法平均每次迭代0.68微秒;正则表达式方法1.14μs; substr方法0.16μs。即使是我最糟糕的情况(2250-char字符串相等),index需要2.4μs,正则表达式需要5.7μs,substr需要0.5μs。

我的建议是编写一个库例程:

sub begins_with
{
    return substr($_[0], 0, length($_[1])) eq $_[1];
}

并将优化工作重点放在其他地方。

更新:基于对我上面描述的“最坏情况”场景的批评,我运行了一组新的基准测试,其中包含一个20,000字符随机生成的字符串,将其与自身进行比较,并将字符串与最后一个字符串进行比较。字节。

对于如此长的字符串,正则表达式解决方案是迄今为止最差的(20,000字符正则表达式是地狱):匹配成功为105μs,匹配失败为100μs。

indexsubstr解决方案仍然非常快。成功/失败index为11.83μs/11.86μs,substr为4.09μs/4.15μs。将代码移动到单独的函数中添加约0.222±0.05μs。

基准代码位于:http://codepaste.net/2k1y8e

我不知道@Sphane数据的特征,但我的建议是。

答案 1 :(得分:2)

另一种选择是将rindex的位置设置为0,这意味着“从位置<= 0开始,在$ str中获取$ substr的索引”,即它仅检查$ substr是否为$的前缀str:

> rindex "abc", "a", 0
0
> rindex "abc", "b", 0
-1