in reply to aliasing

I think you got the answer to your question, but it might be worth pointing out that reverse already has smarts built in to reverse the elements of an array in-place if the source and destination are the same.

# memory use 2368k my @r = 1...1000000; # memory use 62804k @r = reverse @r; # memory use 62812k

As you can see, almost no extra memory is consumed by the process of the reversal. Contrast that with your aliased reverse in which an extra 16MB is consumed to reverse a million element array.

sub r{ @_[ 0 .. $#_ ] = reverse @_; } # memory use 2368k my @r = 1 .. 1000000; # memory use 62812k; r @r; # memory use 78664k;

Using reverse in the normal way is also markedly quicker.

#! perl -slw use strict; use Benchmark qw[ cmpthese ]; sub r{ @_[ 0 .. $#_ ] = reverse @_ } our @n = 1 .. 1000; cmpthese( -3, { normal_reverse => q[ my @r = reverse @n; ], aliased_reverse => q[ my @r = r( @n ); ], }); __END__ P:\test>320771 Rate aliased_reverse normal_reverse aliased_reverse 1360/s -- -78% normal_reverse 6110/s 349% --

Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Timing (and a little luck) are everything!

Replies are listed 'Best First'.
Re: Re: aliasing
by dragonchild (Archbishop) on Jan 12, 2004 at 21:39 UTC
    While not negating your statements, I'd like to point out a third option, with Benchmarking. It's a middle of the road option.
    #!/usr/local/bin/perl use strict; use Benchmark qw[ cmpthese ]; sub r{ @_[ 0 .. $#_ ] = reverse @_ } sub s{ @{$_[0]} = reverse @{$_[0]} } our @n = 1 .. 1000; cmpthese( -3, { normal_reverse => q[ my @r = reverse @n; ], aliased_reverse => q[ my @r = &r( @n ); ], aliased_ref_reverse => q[ &s( \@n ); ], }); __END__ Rate aliased_reverse aliased_ref_reverse norm +al_reverse aliased_reverse 644/s -- -57% + -77% aliased_ref_reverse 1508/s 134% -- + -46% normal_reverse 2793/s 334% 85% + --

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      That certainly stops the memory consumption. For simple reversal, I don't see any benefit, but if the sub is going to do other things as well, I agree that using pass-by-reference rather than value for subs that are designed to modify their arguments makes perfect sense.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Timing (and a little luck) are everything!

Re: Re: aliasing
by ysth (Canon) on Jan 12, 2004 at 22:38 UTC
    I can't comment on your memory statistics, but I definitely see a list-context rv2av or padav for reverse @r, so each element of the array does appear to be put onto the stack.
    $ perl -MO=Concise -we'@r = reverse @r' c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 b <2> aassign[t6] vKS/COMMON ->c - <1> ex-list lK ->8 3 <0> pushmark s ->4 7 <@> reverse[t5] lK/1 ->8 4 <0> pushmark s ->5 6 <1> rv2av[t4] lK/1 ->7 5 <#> gv[*r] s ->6 - <1> ex-list lK ->b 8 <0> pushmark s ->9 a <1> rv2av[t2] lKRM*/1 ->b 9 <#> gv[*r] s ->a -e syntax OK $ perl -MO=Concise -we'my @r; @r = reverse @r' c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 3 <0> padav[@r:1,2] vM/LVINTRO ->4 4 <;> nextstate(main 2 -e:1) v ->5 b <2> aassign[t3] vKS/COMMON ->c - <1> ex-list lK ->9 5 <0> pushmark s ->6 8 <@> reverse[t2] lK/1 ->9 6 <0> pushmark s ->7 7 <0> padav[@r:1,2] l ->8 - <1> ex-list lK ->b 9 <0> pushmark s ->a a <0> padav[@r:1,2] lRM* ->b -e syntax OK

      I have to reverse (sic:) your statement. I can't comment on your opcode dumps -- I don't understand them enough.

      However, it should be fairly simple to test my assertions on the memory consumption.

      I used win32's task manager, but if you inserted a few <>; statements in place of the comments in the snippets I posted, you should be able to use top in another console to watch the memory usage and growth.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Timing (and a little luck) are everything!

        I think what's happening is that the original assignment @r = 1..1000000 is expanding perl's stack to accomodate a million entries. Then reverse @r doesn't require any additional space. But the million entries are still put on the stack and then assigned.