为什么 substr-lvalue 比四参数 substr 快?

问题描述:

来自 这个问题,我们对这两个变体进行基准测试,

From this question, we benchmark these two variants,

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

在其中我们发现 substr-lvalue 更快.池上说,

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

4-arg substr 比左值 substr 慢(它必须创建一个神奇的标量,并且需要额外的操作)???– ikegami

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,

为什么在上述用例中 substr-lvalue 比四参数 substr 快?

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

这只是一个糟糕的基准测试结果.

It was simply a bad benchmark result.

当我复制您的结果时,我在 Windows Susbsytem for Linux 上的 Unbuntu 上使用 perl.假设性能对该系统的外部因素很敏感.

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.

即使在同一台计算机上使用 Windows (Strawberry Perl) 的本机构建,结果也有很大差异:

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...)

我讨厌在我的共享 linux 网络主机上运行基准测试,但它通常会产生更一致的结果.今天也不例外.

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%            --

(我使用了 -3 而不是 100_000_000.)

(I used -3 instead of 100_000_000.)

所有差异均小于或等于 3%,这并不显着.据我所知,一个并不比另一个慢.

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

事实上,人们不应该期望有任何不同.正如 Dave Mitchell 所指出的,substr( $foo, 0, 0 ) = "Hello "; 被优化为几乎等同于 substr( $foo, 0, 0, "Hello "); 自 5.16 起(在 5.20 中有所改进).

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

(唯一的区别是操作数的传递顺序,使用 REPL1ST 标志发出信号.)

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