سؤال

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
  • Does the operation first generate a list via split and create an array ref, then copy the values of the array ref into a new array when dereferencing?
  • Does it morph the current arrayref in place?

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

هل كانت مفيدة؟

المحلول 2

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?

نصائح أخرى

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%    --
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top