pau*_*128 7 regex optimization perl profiling
这更多是出于好奇而不是其他任何事情,因为我没有在Google上找到关于此功能的任何有用信息(CORE :: substcont)
在分析和优化一些旧的,慢的XML解析代码时,我发现以下正则表达式每次执行行时都会调用substcont 31次,并且需要花费大量时间:
通话时间:10000时间:2.65秒子通话:320000潜艇时间:1.15秒
$handle =~s/(>)\s*(<)/$1\n$2/g;
# spent 1.09s making 310000 calls to main::CORE:substcont, avg 4µs/call
# spent 58.8ms making 10000 calls to main::CORE:subst, avg 6µs/call
Run Code Online (Sandbox Code Playgroud)
与前一行相比:
呼叫:10000时间:371ms子呼叫:30000潜艇时间:221ms
$handle =~s/(.*)\s*(<\?)/$1\n$2/g;
# spent 136ms making 10000 calls to main::CORE:subst, avg 14µs/call
# spent 84.6ms making 20000 calls to main::CORE:substcont, avg 4µs/call
Run Code Online (Sandbox Code Playgroud)
substcont调用的数量是非常令人惊讶的,特别是因为我认为第二个正则表达式会更昂贵.这显然是为什么剖析是一件好事;-)
我随后更改了这两行以删除不必要的backrefs,对于表现不佳的行有显着的结果:
通话时间:10000次:393ms次级通话:10000次时间:341ms
$handle =~s/>\s*</>\n</g;
# spent 341ms making 10000 calls to main::CORE:subst, avg 34µs/call
Run Code Online (Sandbox Code Playgroud)
substcont是 Perl 的“替换迭代器”的内部名称。有事与s///. 根据我所掌握的少量信息,它似乎substcont是在进行反向引用时触发的。也就是说,何时$1存在。您可以使用 B::Concise 来玩一下它。
这是没有反向引用的简单正则表达式的操作码。
$ perl -MO=Concise,-exec -we'$foo = "foo"; $foo =~ s/(foo)/bar/ig'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <$> const[PV "foo"] s
4 <#> gvsv[*foo] s
5 <2> sassign vKS/2
6 <;> nextstate(main 1 -e:1) v:{
7 <#> gvsv[*foo] s
8 <$> const[PV "bar"] s
9 </> subst(/"(foo)"/) vKS
a <@> leave[1 ref] vKP/REFC
-e syntax OK
Run Code Online (Sandbox Code Playgroud)
和一。
$ perl -MO=Concise,-exec -we'$foo = "foo"; $foo =~ s/(foo)/$1/ig'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <$> const[PV "foo"] s
4 <#> gvsv[*foo] s
5 <2> sassign vKS/2
6 <;> nextstate(main 1 -e:1) v:{
7 <#> gvsv[*foo] s
8 </> subst(/"(foo)"/ replstart->9) vKS
9 <#> gvsv[*1] s
a <|> substcont(other->8) sK/1
b <@> leave[1 ref] vKP/REFC
-e syntax OK
Run Code Online (Sandbox Code Playgroud)
这就是我能提供的一切。您可能想尝试Rx,mjd 的旧正则表达式调试器。