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); }
});
}