为什么 substr-lvalue 比四参数 substr 快?
Why is substr-lvalue faster than four-arg substr?
从 this question 开始,我们对这两个变体进行了基准测试,
substr( $foo, 0, 0 ) = "Hello ";
substr( $foo, 0, 0, "Hello " );
在其中我们发现 substr
-lvalue 更快。池上说,
How is 4-arg substr slower than lvalue substr (which must create a magical scalar, and requires extra operations)??? – ikegami
说实话,我还认为它会慢得多,只是提到它,因为它是由其他人提出的。纯粹出于好奇,
为什么在上述用例中 substr
-左值比四参数 substr
快?
这只是一个糟糕的基准测试结果。
当我复制你的结果时,我在 Windows Susbsytem for Linux 上使用 Unbuntu 上的 perl。假设性能对该系统的外部因素很敏感。
即使在同一台计算机上使用 Windows (Strawberry Perl) 的本机构建,我的结果也大相径庭:
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% --
时间这么小,机器太忙,无法准确读数。
(在某处有关于微优化的要点...)
我讨厌 运行 我共享的 linux 虚拟主机上的基准测试,但它通常会产生更加一致的结果。今天也不例外。
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
。)
所有差异都在 3% 或更少,这并不显着。据我所知,一个并不比另一个慢。
事实上,人们不应该期待有什么不同。正如 Dave Mitchell 指出的那样,substr( $foo, 0, 0 ) = "Hello ";
自 5.16 以来被优化为实际上等同于 substr( $foo, 0, 0, "Hello " );
的东西(在 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
标志发出信号。)
从5.16.0开始,lvalue+assign变体被优化为4-arg变体(虽然nulled-out NOOP赋值op在5.20.0之前仍然在执行路径中,这稍微减慢了速度) .
从 this question 开始,我们对这两个变体进行了基准测试,
substr( $foo, 0, 0 ) = "Hello ";
substr( $foo, 0, 0, "Hello " );
在其中我们发现 substr
-lvalue 更快。池上说,
How is 4-arg substr slower than lvalue substr (which must create a magical scalar, and requires extra operations)??? – ikegami
说实话,我还认为它会慢得多,只是提到它,因为它是由其他人提出的。纯粹出于好奇,
为什么在上述用例中 substr
-左值比四参数 substr
快?
这只是一个糟糕的基准测试结果。
当我复制你的结果时,我在 Windows Susbsytem for Linux 上使用 Unbuntu 上的 perl。假设性能对该系统的外部因素很敏感。
即使在同一台计算机上使用 Windows (Strawberry Perl) 的本机构建,我的结果也大相径庭:
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% --
时间这么小,机器太忙,无法准确读数。
(在某处有关于微优化的要点...)
我讨厌 运行 我共享的 linux 虚拟主机上的基准测试,但它通常会产生更加一致的结果。今天也不例外。
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
。)
所有差异都在 3% 或更少,这并不显着。据我所知,一个并不比另一个慢。
事实上,人们不应该期待有什么不同。正如 Dave Mitchell 指出的那样,substr( $foo, 0, 0 ) = "Hello ";
自 5.16 以来被优化为实际上等同于 substr( $foo, 0, 0, "Hello " );
的东西(在 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
标志发出信号。)
从5.16.0开始,lvalue+assign变体被优化为4-arg变体(虽然nulled-out NOOP赋值op在5.20.0之前仍然在执行路径中,这稍微减慢了速度) .