Reputation: 42139
I'm curious if Perl internals creates a copy of the ref values to create the array? For example, the following outputs the last and first value of a delimited string:
say @{[ split( q{\|}, q{bar|is|foo} ) ]}[-1,0]; # STDOUT: foobar\n
split
and create an array ref, then copy the values of the array ref into a new array when dereferencing? Because dereferencing is so common I'm sure it's optimized, I'm just curious how expensive it is versus creating an array from the list initially, like:
my @parts = split q{\|}, q{bar|is|foo};
say @parts[-1,0];
Purpose: getting an idea of the underlying operations w/o getting too deep into the code
Upvotes: 7
Views: 511
Reputation: 386331
vol7ron> How expensive is it to dereference an array ref in Perl?
ikegami> You're doing more than just dereferencing an array.
vol7ron> But the question still stands
Again, this is a useless question. The alternative is never between simply dereferencing an array and something else.
But since you insist, it's 37 ns (37 billionths of a second) for me.
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);
}
Result:
Rate deref none
deref 3187659/s -- -12%
none 3616848/s 13% --
Time taken by each deref = 1/3187659 s - 1/3616848 s = 37 ns
It's tiny! Dereferencing the array only accounts for 12% of the time taken to dereference an empty array and copying it into another!
Does the operation first generate a list via split (1) and create an array ref (2), then copy the values of the array ref into a new array when dereferencing (3)?
Yes, split
returns a list. Except in scalar context.
[ ... ]
doesn't just create a reference, it also creates an array and copies the values into it.
No, dereferencing doesn't copy values.
Does it morph the current arrayref in place?
It would be really bad if a reference turned into something else. What do you actually mean?
Upvotes: 1
Reputation: 91488
Here is a Benchmark
#!/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];
},
});
I just change say
to an assignement.
Windows 7, perl 5.14.2
Rate deref array
deref 2.02/s -- -38%
array 3.23/s 60% --
Depending of environment, I get
Linux 64 bit, perl 5.14.2
Rate deref array
deref 3.00/s -- -35%
array 4.65/s 55% --
and Linux 32 bit, perl 5.8.4
Rate array deref
array 1.96/s -- -35%
deref 3.00/s 53% --
Upvotes: 3