in reply to returning arrays from a sub - how clever is Perl?

Your first snippet just explicitly conveys some logic that otherwise must go on behind the scenes.

I was curious as to the performance hit of invoking wantarray and scalar along with a trinary operator, as opposed to allowing the internals to take care of the decision. So I wrote a sample test that creates an array of 20,000 elements (by preextending an empty array by assigning a value to $#array).

I then wrote two functions; one with your wantarray logic and one without, put them side by side, and wrote wrapper functions for them that invoked each function twice; once in scalar and once in list context. I then used Benchmark to test.

The results were seemingly inconclusive even for such a large array, and going through 5000 iterations of the test. But then I realized that I was testing more the speed of returning an array than the speed of testing the logic. So I changed it to 50,000 iterations on an array of 1000 elements. ...and the results were... inconclusive. Or at least, the results indicated that there is no significant difference between the first and the second construct.

Update: hardburn points out that there is a flaw in my test. However I had already refined it to what I believe to be a better comparison. See the discussion in this node for the more accurate test.

Here is the code I used to test:

use strict; use warnings; use Benchmark; my @array; $#array = 1000; sub with_want { return wantarray ? @array : scalar @array; } sub without { return @array; } sub test_with { my @testary = with_want(); my $testscalar = with_want(); } sub test_without { my @testary = with_want(); my $testscalar = with_want(); } my $count = 50000; timethese ( $count, { "With wantarray" => \&test_with, "Without wantarray" => \&test_without } ); __OUTPUT__ Benchmark: timing 50000 iterations of With wantarray, Without wantarra +y... With wantarray: 16 wallclock secs (17.50 usr + 0.01 sys = 17.52 CPU) +@ 2854.70/s (n=50000) Without wantarray: 18 wallclock secs (17.47 usr + 0.01 sys = 17.48 CP +U) @ 2859.59/s (n=50000)

I'm far from being an expert on constructing benchmark tests. This particular test is probably still flawed in ways that I haven't considered.

But the preliminary result is that it doesn't make any difference from an efficiency standpoint which method you use.

UPDATE: Thanks hardburn for pointing out the flaw in this comparison. I would rewrite it except that I've already created a better comparison elsewhere in this thread, that more clearly demonstrates the issue. You'll find a more accurate discussion here: Re: Re: Re: returning arrays from a sub - how clever is Perl?.


Dave


"If I had my life to do over again, I'd be a plumber." -- Albert Einstein

Replies are listed 'Best First'.
Re: Re: returning arrays from a sub - how clever is Perl?
by revdiablo (Prior) on Oct 22, 2003 at 03:47 UTC

    I thought your benchmark was pretty good, but I thought it'd be interesting to see the performance of each in scalar and array context by themselves. So without further ado, here is the benchmark code I used:

    And here are the results:

    To me these are interesting for several reasons. They are fairly consistent with your results -- for the array context, at least. They also show the version without explicit context check to be faster in scalar context. Note the extremely high rate makes the results somewhat useless, but interesting nonetheless.

      ... show the version without explicit context check to be faster in scalar context
      Ahhh! So maybe Perl is clever after all. I thought that it should be.

      Cheers!

Re: Re: returning arrays from a sub - how clever is Perl?
by hardburn (Abbot) on Oct 22, 2003 at 13:47 UTC
    sub test_with { my @testary = with_want(); my $testscalar = with_want(); } sub test_without { my @testary = with_want(); my $testscalar = with_want(); }

    I'd expect the results to be similar, since you're testing the exact same thing! I think you want that second one to be:

    sub test_without { my @testary = without(); my $testscalar = without(); }

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    :(){ :|:&};:

    Note: All code is untested, unless otherwise stated