【问题标题】:Why is substr-lvalue faster than four-arg substr?为什么 substr-lvalue 比四参数 substr 快?
【发布时间】:2020-05-08 01:25:30
【问题描述】:

来自this question,我们对这两个变体进行了基准测试,

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

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

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

说实话,我还认为它会慢很多,只是提到它是因为它是由其他人提出的。纯粹出于好奇,

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

【问题讨论】:

标签: perl substr microbenchmark


【解决方案1】:

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

当我复制您的结果时,我在 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 web 主机上运行基准测试,但它通常会产生更一致的结果。今天也不例外。

                   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 标志表示。)

【讨论】:

  • 是的,对我来说,即使是 -3,我在 debian 和 Buster 上也有很大的不同。
  • -3 vs 100_000_000 除了运行多长时间(3 秒 vs 100_000_000 测试)之外,不会有任何区别
  • 对我来说 substr_lvalue 与 multiconcat 差不多,并且在 Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz 上总是比 substr 快
  • 我们说的是每次交互大约 100 ns 的时间包括相对昂贵的子调用。它受到波动的影响也就不足为奇了。在测试这样的东西时,我使用b_multiconcat =&gt; 'use strict; use warnings; for (1..1000) { my $foo = "world!"; $foo = "Hello $foo"; }'
  • @ikegami 只是想知道,您使用什么命令来获取这些结果数据?
【解决方案2】:

从 5.16.0 开始,lvalue+assign 变体已优化为 4-arg 变体(尽管在 5.20.0 之前,空值的 NOOP 赋值操作仍在执行路径中,这稍微减慢了它的速度)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 2015-06-01
    • 2021-08-20
    相关资源
    最近更新 更多