in reply to Re: Re^6: Shifty Politics
in thread stoping and restarting a loop

My argument is simply that using shift to extract several arguments is usually inefficient and, by induction, not very desirable:
my ($foo_a) = @_; # Simple my $foo_a = shift; # Comparable my ($foo_a) = (shift); # Odd my ($foo_a, $foo_b) = @_; # Typical my ($foo_a, $foo_b) = (shift, shift); # Odder my ($foo_a, $foo_b, $foo_c, $foo_d) = @_; my ($foo_a, $foo_b, $foo_c, $foo_d) = (shift, shift, shift, shift);
The last one is, I hope you'll agree, outrageous, and is best reserved for those sitations where you'd explain it, but it's a "long story".

I'm not saying that you shouldn't use shift. You can program any way you like. You can also use goto with impunity, variable names that make no sense, and use substr and unpack instead of regular expressions. What I'm suggesting is that using multiple shifts in a function is poor form and is a bad habit to develop.

Oh, and a goto by any other name still smells as rotten. I'd like to see any Benchmark that could show that using that technique you describe could provide measurable performance gains. As far as I can tell, passing the whole args array is fairly efficient. Pulling them apart and repacking them isn't.

Replies are listed 'Best First'.
Re: Re^8: How about 450% greater performance
by BrowserUk (Patriarch) on Sep 10, 2002 at 23:00 UTC

    I'd like to see any Benchmark that could show that using that technique you describe could provide measurable performance gains.

    #! perl -w use strict; use Benchmark qw(cmpthese); sub parent { return ++$_[$#_]; # minimal use of entire passed array. } sub child1 { my ($self, @rest) = @_; return parent(@rest); } sub child2 { my $self = shift; goto &parent; } print 'child1: ', child1( "fred", 1..1000 ), $/; print 'child2: ', child2( "bill", 1..1000 ), $/; cmpthese( 10000, { noShiftOrGoto => sub { child1( "fred", 1..1000 ); }, shiftAndGoto => sub { child2( "bill", 1..1000 ); }, }); __DATA__ C:\test>196823 child1: 1001 child2: 1001 Benchmark: timing 10000 iterations of noShiftOrGoto, shiftAndGoto... noShiftOrGoto: 33 wallclock secs (32.33 usr + 0.00 sys = 32.33 CPU) @ + 309.35/s (n=10000) shiftAndGoto: 6 wallclock secs ( 5.85 usr + 0.00 sys = 5.85 CPU) @ +1709.69/s (n=10000) Rate noShiftOrGoto shiftAndGoto noShiftOrGoto 309/s -- -82% shiftAndGoto 1710/s 453% -- C:\test>

    Well It's better than the Abottoire, but Yorkshire!
      That's not precisely a fair test. How about this?
      #!/usr/bin/perl use Benchmark 'cmpthese'; package Foo; sub new { my $class = shift; bless({@_}, $class); } sub foo { my ($self, @stuff) = @_; return map { $_.$_ } @stuff; } sub foo_pipe { my $self = shift; $self->foo(@_); } sub foo_my { my ($self,@stuff) = @_; $self->foo(@stuff); } sub foo_goto { goto &foo; } package main; my $foo = Foo->new(); my @stuff = 0..100; my @foo; cmpthese(500, { pipe => sub { $foo->foo_pipe(@foo=@stuff) }, goto => sub { $foo->foo_goto(@foo=@stuff) }, my => sub { $foo->foo_my(@foo=@stuff) }, });
      This actually uses the entire array. The difference is rather minor, easily buried by the subroutine overhead.
      Benchmark: timing 5000 iterations of goto, my, pipe... goto: 3 wallclock secs ( 2.96 usr + 0.00 sys = 2.96 CPU) @ 16 +89.19/s (n=5000) my: 4 wallclock secs ( 3.18 usr + 0.01 sys = 3.19 CPU) @ 15 +67.40/s (n=5000) pipe: 3 wallclock secs ( 2.89 usr + 0.00 sys = 2.89 CPU) @ 17 +30.10/s (n=5000) Rate my goto pipe my 1567/s -- -7% -9% goto 1689/s 8% -- -2% pipe 1730/s 10% 2% --