h2 has asked for the wisdom of the Perl Monks concerning the following question:

While getting to that point of a project where optimizing and reviewing my Perl chops begins to seem like a good idea, i decided to check on some assumptions I'd made. Well, ok, not assumptions, I was following what basically most articles on the topic of passing by reference or by copy seem to say, and which I'd, sadly, followed without verifying the murky depths of mythology myself.

This post helped me in my path, and of course, reminded me of the vast pool of things I don't know: Performance issues with subroutines/methods

So I decided to test it, sure in my faith, for faith is what it turns out to be, that of course, passing by reference must always be fast than passing copies, since, well, Perl doesn't have to work much to use a references, but it has todo all kinds of work when it creates copies.

So I tested it:

use strict; use warnings; use Benchmark qw(:all); my @a = ( 'a','b','c','d','e','g','h', 'a','b','c','d','e','g','h', 'a +','b','c','d','e','g','h', 'a','b','c','d','e','g','h', 'a','b','c',' +d','e','g','h', 'a','b','c','d','e','g','h', 'a','b','c','d','e','g', +'h', 'a','b','c','d','e','g','h', 'a','b','c','d','e','g','h', 'a','b +','c','d','e','g','h', ); my $a_ref = [ 'a','b','c','d','e','g','h', 'a','b','c','d','e','g','h' +, 'a','b','c','d','e','g','h', 'a','b','c','d','e','g','h', 'a','b',' +c','d','e','g','h', 'a','b','c','d','e','g','h', 'a','b','c','d','e', +'g','h', 'a','b','c','d','e','g','h', 'a','b','c','d','e','g','h', 'a +','b','c','d','e','g','h', ]; cmpthese(-2, { 'a copy' => sub { my @b = a_copy(@a); }, 'a ref 1' => sub { my $b = a_ref_1(\@a); }, 'a ref 2' => sub { my $b = a_ref_2(\@a); }, 'a ref 3' => sub { my $b = a_ref_1($a_ref); }, 'a ref 4' => sub { my $b = a_ref_2($a_ref); }, }); sub a_copy { my (@a) = @_; return @a; } sub a_ref_1 { my ($a) = @_; return $a; } sub a_ref_2 { return $_[0]; }


Which returned, much to my dismay, the following:

Rate a copy a ref 1 a ref 3 a ref 2 a ref 4 a copy 171189/s -- -97% -97% -97% -98% a ref 1 5073751/s 2864% -- -15% -21% -35% a ref 3 5946679/s 3374% 17% -- -7% -23% a ref 2 6408282/s 3643% 26% 8% -- -17% a ref 4 7753141/s 4429% 53% 30% 21% --


The larger I made the test arrays, the larger the gaps grew, if I made them 2x larger, they took 2x longer for references, roughly, it seemed failrly linear.

What am I missing here? I fear I have somehow totally missed some core, essential feature of Perl during this journey, which is, sadly, all too likely, but this really did not meet my expections or beliefs at all. Note that following the notion that references must always be faster, I actually converted a big chunk of a big project to always pass hashes and arrays to subs by reference, not by copying, and now I'm wincing that I did not test this first.

Note that in the above, I speculated that maybe Perl had to work extra hard to create a reference at every iteration using (\@a) so I also created a pre-referenced array, and passed the scalar directly in, and, again, much to my conceptual dismay, that was even slower!!! How can this be? I mean, this data clearly suggests that I should never pass back or forth by reference, so what am I missing here?

I realize during all spiritual journeys, we hit stumbling blocks, challenges, and so on, and that at times. we must consult with our gurus to obaz

Update:

Delete this if needed, I was just misreading, badly, some results, and the question has no relevance and is only a warning to others that sometimes it's good to step away from the keyboard for a few days when you start making mistakes this bad. My apologies to the monks.

Replies are listed 'Best First'.
Re: A matter of sub pass by reference or copy
by choroba (Cardinal) on Mar 13, 2021 at 20:29 UTC
    The table tells us that the "copy" was able to run 171189 times per second, while the "ref 1" was able to run 5073751 times per second, i.e. 29 times faster.

    Note that in practice, if you need to access each element of the array, repeated dereferencing can be slower than accessing the elements directly.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      It's clearly time for me to step away from this, I've obviously been burning the candles at both ends for a bit too long, I blame my damaged brain for not seeing it so clearly. should I just remove this post since it's just about brain damage and lack of vision and not an actual problem, sigh.

        G'day h2,

        "... should I just remove this post ..."

        Well, it looks like you've done that already. This has rendered the only reply meaningless. Please see "How do I change/delete my post?" for a detailed discussion about this.

        I don't know what the original looked like, but a better way to handle this situation would be something like:

        Update: Please ignore! I was just misreading, badly, ... candle-burning ... brain damage ... yada yada. My apologies to the monks.

        Start of the original post ...

        ... end of the original post.

        Now, anyone coming to this thread for the first time, not only knows to ignore the original post, but can also make sense of any replies.

        By the way, striking out the original post can be most easily done by wrapping it with <strike>...</strike>. The markup for my example is:

        <strike> <p> Start of the original post ... </p> <p> ... end of the original post. </p> </strike>

        — Ken

Re: A matter of sub pass by reference or copy
by Anonymous Monk on Mar 14, 2021 at 20:12 UTC
    Wish you'd put your original post text back, because someone else is going to make the same mistake someday.