String 使用“搜索”进行子字符串搜索时出现性能差异的原因是什么;索引();Perl中的vs正则表达式?

String 使用“搜索”进行子字符串搜索时出现性能差异的原因是什么;索引();Perl中的vs正则表达式?,string,perl,search,String,Perl,Search,我假设以下两者之间可能存在效率差异: if (index($string, "abc") < -1) {} 有人能根据两者在Perl中的实现方式(与纯基准测试相反)来确认这一点吗 很明显,我可以猜测这两种语言是如何实现的(基于我将如何用C编写这两种语言),但我希望得到更明智的答案,最好是基于实际的perl源代码 以下是我自己的基准测试示例: Rate regex.FIND_AT_END index.FIND_AT_END regex.FIND_AT_END 639345/

我假设以下两者之间可能存在效率差异:

if (index($string, "abc") < -1) {}
有人能根据两者在Perl中的实现方式(与纯基准测试相反)来确认这一点吗

很明显,我可以猜测这两种语言是如何实现的(基于我将如何用C编写这两种语言),但我希望得到更明智的答案,最好是基于实际的
perl
源代码


以下是我自己的基准测试示例:

Rate regex.FIND_AT_END index.FIND_AT_END regex.FIND_AT_END 639345/s -- -88% index.FIND_AT_END 5291005/s 728% -- Rate regex.NOFIND index.NOFIND regex.NOFIND 685260/s -- -88% index.NOFIND 5515720/s 705% -- Rate regex.FIND_AT_START index.FIND_AT_START regex.FIND_AT_START 672269/s -- -90% index.FIND_AT_START 7032349/s 946% --
看看函数:

430字符*
431 Perl_instr(寄存器常量字符*大,寄存器常量字符*小)
432 {
433首先是寄存器I32;
434
435 PERL_ARGS_ASSERT_INSTR;
436
437如果(!很少)
438返回(字符*)大;
439 first=*little++;
440如果(!第一个)
441返回(字符*)大;
442而(*大){
443寄存器常量字符*s,*x;
444如果(*大++!=第一个)
445继续;
446表示(x=大,s=小;*s;/**/){
447如果(!*x)
448返回空;
449如果(*s!=*x)
450次中断;
451其他{
452s++;
453x++;
454             }
455         }
456如果(!*s)
457返回(字符*)(大1);
458     }
459返回空;
460 }

与…相比。在我看来,
regmatch
index
;-)相比有一些开销

顺便说一句,如果我的基准不是测试这些的最佳方法,请提出一个更合适的方法。这更像是一个在回答这个问题时突然出现在我脑海中的理论问题:你能添加第三个测试吗:
“rege2.$type”=>sub{my$idx=($str=~/abc/o);}
,有趣的是(或者不是?),它的结果与我的机器上的正则表达式测试(perl 5.12.3)不同,更接近于
索引
的情况。您是否尝试使用更长的字符串?在Mac OS Lion和homebrew上,使用16K字符串,我发现
find_AT_END
NOFIND
之间没有太大区别
FIND_AT_START
的速度仍然更快。另外,IIRC,
/o
开关仅在较旧的
perl
s上相关,即使是在有变量插值的情况下也是如此。你忘了在你的轻描淡写中加上“:)@DVK当然,为了得到真正的答案,人们必须真正了解
/abc/
会发生什么,我不想开始理解它。但是,是的,如果我能说一口地道的英国口音那就太好了。 Rate regex.FIND_AT_END index.FIND_AT_END regex.FIND_AT_END 639345/s -- -88% index.FIND_AT_END 5291005/s 728% -- Rate regex.NOFIND index.NOFIND regex.NOFIND 685260/s -- -88% index.NOFIND 5515720/s 705% -- Rate regex.FIND_AT_START index.FIND_AT_START regex.FIND_AT_START 672269/s -- -90% index.FIND_AT_START 7032349/s 946% --
##############################
use Benchmark qw(:all);

my $count = 10000000;
my $re = qr/abc/o;
my %tests = (
    "NOFIND        " => "cvxcvidgds.sdfpkisd[s"
   ,"FIND_AT_END   " => "cvxcvidgds.sdfpabcd[s"
   ,"FIND_AT_START " => "abccvidgds.sdfpkisd[s"
);

foreach my $type (keys %tests) {
    my $str = $tests{$type};
    cmpthese($count, {
        "index.$type" => sub { my $idx = index($str, "abc"); },
        "regex.$type" => sub { my $idx = ($str =~ $re); }
    });
}