为什么+ = vs +中的性能差异?

drc*_*law 14 perl6

调试一些代码最终测试了语句中的差异,例如$counter=$counter + 1;vs$counter+=1;

my $run=True;
my $counter=0;
my $sup=Supply.interval(1);
my $tap= $sup.tap({
    $run=$_ < 10;
});
{
    while $run {
        #$counter+=1;
        $counter=$counter + 1;
    }
    $tap.close;
    say "Iterations per second: {$counter/(now - ENTER now)}"; #
}
Run Code Online (Sandbox Code Playgroud)

与之$counter=$counter+1相比, 我每秒获得约20%的迭代$counter+=1;

在后台发生了什么,那是如此不同?

编辑:

有趣的是,当使用数组和超级运算符尝试此操作时,使用时性能会大大 提高+=

例如, @counter=@counter>>+<<@value; 与 10_000个元素的数组一起@counter>>+=<<@value; 使用>>+=<<,我得到的循环迭代次数约为2.8倍。

据我可以通过timecmd 得知,在任何一种情况下,并行执行最少(总用户+系统在实时的2%之内)。

关于如何/为什么这样的任何见解都是很棒的。谢谢!

Eli*_*sen 16

我已将您的基准设定为:

my $a = 0; for ^10_000_000 { $a += 1 }
Run Code Online (Sandbox Code Playgroud)

vs:

my $a = 0; for ^10_000_000 { $a = $a + 1 }
Run Code Online (Sandbox Code Playgroud)

如果使用来在事件探查器中运行这些示例perl6 --profile -e '...',那么您会发现差异确实在20%范围内。唯一真正不同的是帧总数:的49935579 += 1和的39932197 = $a + 1

根本的区别(在进行任何优化之前)是+=通过元操作路径。它没有定义为单独的运算符,因此需要动态创建运算符,将原始运算符(&infix:<+>)作为参数并从中建立一个Callable

FWIW,我很高兴看到如今的差异仅为20%:不久前,涉及metaops的任何事物的速度至少慢了两倍:-)

  • 有趣。我决定在我的机器上运行它,并添加了$ a ++变体,它比其他两个变体更糟。 (3认同)