在Perl中取消引用数组引用有多贵?

vol*_*ron 6 perl dereference

我很好奇Perl internals是否创建了ref值的副本来创建数组?例如,以下输出分隔字符串的最后一个和第一个值:

say @{[ split( q{\|}, q{bar|is|foo} ) ]}[-1,0];     # STDOUT: foobar\n
Run Code Online (Sandbox Code Playgroud)
  • 操作是否首先通过生成列表split并创建数组引用,然后在解除引用时将数组ref的值复制到新数组中?
  • 它是否将当前的arrayref变形?

因为解除引用是如此常见,我确信它已经过优化,我只是好奇它与最初从列表中创建数组相比有多昂贵,例如:

my @parts = split q{\|}, q{bar|is|foo};
say @parts[-1,0];
Run Code Online (Sandbox Code Playgroud)

目的:了解底层操作,而无需深入了解代码

ike*_*ami 1

vol7ron> 在 Perl 中取消引用数组 ref 的成本有多高?

ikegami> 您所做的不仅仅是取消引用数组。

vol7ron> 但问题仍然存在

再说一遍,这是一个无用的问题。替代方案绝不是简单地取消引用数组和其他东西。

但既然你坚持,那对我来说就是 37 纳秒(十亿分之三十七)。

use Benchmark qw( cmpthese );

my %tests = (
   deref => 'my @y = @$x;',
   none  => 'my @y = @x;',
);

$_ = 'use strict; use warnings; our $x; our @x; ' . $_
   for values %tests;

{
   local our @x = ();
   local our $x = \@x;
   cmpthese(-3, \%tests);
}
Run Code Online (Sandbox Code Playgroud)

结果:

           Rate deref  none
deref 3187659/s    --  -12%
none  3616848/s   13%    --
Run Code Online (Sandbox Code Playgroud)

每次 deref 所需的时间 = 1/3187659 s - 1/3616848 s = 37 ns

它很小!取消引用数组仅占取消引用空数组并将其复制到另一个数组所需时间的 12%!

该操作是否首先通过 split (1) 生成列表并创建数组 ref (2),然后在取消引用时将数组 ref 的值复制到新数组中 (3)?

  1. 是的,split返回一个列表。标量环境除外。

  2. [ ... ]不只是创建一个引用,它还创建一个数组并将值复制到其中。

  3. 不,取消引用不会复制值。

它会改变当前的 arrayref 吗?

如果参考文献变成了其他东西,那就太糟糕了。你到底是什么意思?