my @arr = qw( one two three );
sub while_with_shift_push {
my $ref;
my @cp = @arr;
push( @$ref, $_ ) while( $_ = shift( @cp ) );
return $ref;
}
sub for_with_push {
my $ref;
my @cp = @arr;
push( @$ref, shift( @cp ) ) for ( 0..$#cp );
return $ref;
}
sub splice_it {
my $ref;
my @cp = @arr;
push( @$ref, splice( @cp ) );
return $ref;
}
sub push_with_clear {
my @cp = @arr;
my $ref;
push( @$ref, @cp );
@cp = ();
return $ref;
}
You can see we're basically testing four methods of doing the exact same thing to see what's faster.
Rate for_with_push while_with_shift_push push_with_clear splice_it
for_with_push 160238/s -- -9% -32% -43%
while_with_shift_push 175370/s 9% -- -26% -37%
push_with_clear 237079/s 48% 35% -- -15%
splice_it 280139/s 75% 60% 18% --
Of course, as I noted above, it's not really known what the size of the list will be. Therefore, for the next test, I increased the size of the list we were going to mull over to an array of integers 100000 deep. Not reality (yet), though will give a good example of what I am trying to express in this post. Using the same benchmark, here are the findings:
Rate for_with_push splice_it push_with_clear while_with_shift_push
for_with_push 15.8/s -- -47% -50% -77%
splice_it 29.6/s 88% -- -5% -56%
push_with_clear 31.3/s 98% 6% -- -54%
while_with_shift_push 67.7/s 330% 129% 117% --
Completely different once the size of the array has ballooned. Interesting.
for_with_push 131415/s -- -14% -43% -45% while_with_shift_push 152026/s 16% -- -34% -37% push_with_clear 231941/s 76% 53% -- -4% splice_it 240402/s 83% 58% 4% --Similar to the small list of strings, not totally surprising.
Rate for_with_push while_with_shift_push splice_it push_with_clear
for_with_push 73074/s -- -1% -45% -46%
while_with_shift_push 73539/s 1% -- -45% -46%
splice_it 133132/s 82% 81% -- -2%
push_with_clear 136236/s 86% 85% 2% --
Again, completely different from before.
The point:
I tested four ways of doing the same thing, yet in all cases the scope of my problem was just a little different, yet all had completely different results.
A couple of notes:
splice_it makes an entire copy of the array on the stack. It could have been hitting the limits of your system's memory in the test with the array of 100000 items.
while( $_ = shift( @cp ) ); is not equivalent to the others. It will end prematurely if a numeric zero (0), a string zero ('0'), a nul string ('') or an undefined value is encountered in @cp. Perhaps you should have used:
sub while_with_shift_push {
my $ref;
my @cp = @arr;
push( @$ref, shift( @cp ) ) while @cp;
return $ref;
}
Probably irrelevant, but for ( 0..$#cp ) used more memory and was probably slower than for (my $i=@cp; $i--; ) in older versions of Perl.
Unless you plan on working with very long lists, I'd use splice_it. It's the easiest to read of the solutions with similar performance. (And this "unless" prooves your point.)
Also, for clearing it, what about $#cp = -1;? On some Perls, particularly older ones, that's the fastest way to make the contents of an array unaccessible.
It's been pointed out here before, but in general it's more effective to develop an efficient algorithm, than to try to squeeze cycles out by trying different functions or operators. If you're really pressed for time, it would be better to switch to a faster language, like C. IMNSHO.
perlmonks.org content © perlmonks.org and dragonchild, ikegami, spiritway, wazzuteke
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03