vol7ron
vol7ron

Reputation: 42139

How expensive is it to dereference an array ref in Perl?

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

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

Answers (2)

ikegami
ikegami

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)?

  1. Yes, split returns a list. Except in scalar context.

  2. [ ... ] doesn't just create a reference, it also creates an array and copies the values into it.

  3. 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

Toto
Toto

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

Related Questions