Why is substr-lvalue faster than four-arg substr?

旧城冷巷雨未停 提交于 2020-05-15 07:29:07

问题


From this question, we benchmark these two variants,

substr( $foo, 0, 0 ) = "Hello ";
substr( $foo, 0, 0, "Hello " );

In it we discover that substr-lvalue is faster. To which Ikegami said,

How is 4-arg substr slower than lvalue substr (which must create a magical scalar, and requires extra operations)??? – ikegami

Truth be told, I also assumed that it would be massively slower and just mentioned it because it was brought up by someone else. Purely for curiosity,

Why is substr-lvalue faster than four-arg substr in the above usecase?


回答1:


It was simply a bad benchmark result.

When I replicated your results, I was using perl on Unbuntu on Windows Susbsytem for Linux. Let's just say that performance is sensitive to external factors on that system.

Even when using a native build for Windows (Strawberry Perl) on the same computer, I get wild differences in the results:

                   Rate        substr substr_valute   multiconcat
                  Rate substr_valute        substr   multiconcat
substr_valute 6997958/s            --           -0%          -27%
substr        7007667/s            0%            --          -26%
multiconcat   9533733/s           36%           36%            --

                   Rate        substr substr_valute   multiconcat
substr        6795650/s            --           -0%          -10%
substr_valute 6805545/s            0%            --          -10%
multiconcat   7526593/s           11%           11%            --

                    Rate        substr substr_valute   multiconcat
substr         7513339/s            --          -22%          -28%
substr_valute  9693997/s           29%            --           -6%
multiconcat   10367639/s           38%            7%            --

                    Rate        substr   multiconcat substr_valute
substr         8791152/s            --          -13%          -14%
multiconcat   10139954/s           15%            --           -1%
substr_valute 10240638/s           16%            1%            --

The times are just so small, and the machine is just too busy to get accurate readings.

(There's a point to be made about micro-optimizations in there somewhere...)

I hate running benchmarks on my shared linux web host, but it normally produces far more consistent results. Today was no exception.

                   Rate        substr substr_valute   multiconcat
substr        4293130/s            --           -3%          -13%
substr_valute 4407446/s            3%            --          -11%
multiconcat   4938717/s           15%           12%            --

                   Rate substr_valute        substr   multiconcat
substr_valute 4289732/s            --           -2%          -16%
substr        4356113/s            2%            --          -15%
multiconcat   5096889/s           19%           17%            --

(I used -3 instead of 100_000_000.)

All differences are 3% or less, which isn't significant. As far as I can tell, one isn't slower than the other.

In fact, one shouldn't expect any difference. As pointed out by Dave Mitchell, substr( $foo, 0, 0 ) = "Hello "; is optimized into something virtually equivalent to substr( $foo, 0, 0, "Hello " ); since 5.16 (with an improvement in 5.20).

$ perl -MO=Concise,-exec -e'substr( $foo, 0, 0, "Hello " );'
1  <0> enter
2  <;> nextstate(main 1 -e:1) v:{
3  <#> gvsv[*foo] s
4  <$> const[IV 0] s
5  <$> const[IV 0] s
6  <$> const[PV "Hello "] s
7  <@> substr[t2] vK/4
8  <@> leave[1 ref] vKP/REFC
-e syntax OK

$ perl -MO=Concise,-exec -e'substr( $foo, 0, 0 ) = "Hello ";'
1  <0> enter
2  <;> nextstate(main 1 -e:1) v:{
3  <$> const[PV "Hello "] s
4  <#> gvsv[*foo] s
5  <$> const[IV 0] s
6  <$> const[IV 0] s
7  <@> substr[t2] vKS/REPL1ST,3
8  <@> leave[1 ref] vKP/REFC
-e syntax OK

(The only difference is the order in which the operands are passed, which is signaled using the REPL1ST flag.)




回答2:


Since 5.16.0, the lvalue+assign variant has been optimised into the 4-arg variant (although the nulled-out NOOP assignment op was still in the execution path until 5.20.0, which slowed it down slightly).



来源:https://stackoverflow.com/questions/61670492/why-is-substr-lvalue-faster-than-four-arg-substr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!