我很好奇Perl内部是否创建了ref值的副本来创建数组?例如,以下输出分隔字符串的最后一个值和第一个值:
say @{[ split( q{\|}, q{bar|is|foo} ) ]}[-1,0]; # STDOUT: foobar\n
split
生成列表并创建数组引用,然后在解除引用时将数组ref的值复制到新数组中? 因为解除引用是如此常见,我确信它已经过优化,我只是好奇它与最初从列表中创建数组相比有多昂贵,例如:
my @parts = split q{\|}, q{bar|is|foo};
say @parts[-1,0];
目的:了解基础操作,而无需深入了解代码
答案 0 :(得分:3)
这是基准
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Benchmark qw(:all);
my @list = ('foo')x1_000_000;
my $str = join('|',@list);
my $count = -2;
cmpthese($count, {
'deref' => sub {
my $parts = [ split( q{\|}, $str ) ];
my @res = @$parts[-1,0];
},
'array' => sub {
my @parts = split q{\|}, $str;
my @res = @parts[-1,0];
},
});
我只是将say
更改为分配
Windows 7,perl 5.14.2
Rate deref array
deref 2.02/s -- -38%
array 3.23/s 60% --
根据环境,我得到了 Linux 64位,perl 5.14.2
Rate deref array
deref 3.00/s -- -35%
array 4.65/s 55% --
和Linux 32位,perl 5.8.4
Rate array deref
array 1.96/s -- -35%
deref 3.00/s 53% --
答案 1 :(得分:1)
vol7ron>在Perl中取消引用数组引用有多贵?
池上>您所做的不仅仅是取消引用数组。
vol7ron>但问题仍然存在
同样,这是一个无用的问题。替代方案永远不会简单地解除引用数组和其他内容。
但是既然你坚持认为,对我来说这是37 ns(370亿分之一秒)。
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);
}
结果:
Rate deref none
deref 3187659/s -- -12%
none 3616848/s 13% --
每个deref所需的时间= 1/3187659 s - 1/3616848 s = 37 ns
太小了!取消引用该数组只占取消引用空数组并将其复制到另一个数组所用时间的12%!
操作是否首先通过split(1)生成列表并创建数组ref(2),然后在解除引用(3)时将数组ref的值复制到新数组中?
是的,split
会返回一个列表。除了标量上下文外。
[ ... ]
不仅会创建引用,还会创建一个数组并将值复制到其中。
不,取消引用不会复制值。
它是否会将当前的arrayref变形?
如果引用转变为其他内容,那将非常糟糕。你究竟是什么意思?