I had similar results even with longer arrays: #!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw( cmpthese );
my @array = map { int rand 100 } 1 .. 1_000_000;
cmpthese -10, {
op => sub {
my ($min, $max, $avg) = min_max_avg(\@array);
},
simple => sub {
my ($min, $max, $avg) = min_max_avg_simple(\@array);
},
};
sub min_max_avg_simple {
my $ref = shift;
my $n_elements = scalar @$ref;
return unless $n_elements > 0;
my ( $min, $max, $sum ) = ($ref->[0]) x 3;
my $i = 1; # Start from next element
while ($i < $n_elements) {
my $value = $ref->[$i];
if ($value < $min)
{ $min = $value }
elsif ($value > $max)
{ $max = $value }
$sum += $value;
++$i;
}
return ( $min, $max, $sum / $n_elements );
}
sub min_max_avg {
my $ref = shift;
my ( $min, $max, $agv, $i );
my ( $current_min, $current_max );
if ( @{$ref} % 2 == 0 ) {
( $min, $max ) =
$ref->[0] < $ref->[1]
? ( $ref->[0], $ref->[1] )
: ( $ref->[1], $ref->[0] );
$agv = $ref->[0] + $ref->[1];
$i = 2;
}
else {
$min = $max = $agv = $ref->[0];
$i = 1;
}
while ( $i < @{$ref} ) {
( $current_min, $current_max ) =
$ref->[$i] < $ref->[ $i + 1 ]
? ( $ref->[$i], $ref->[ $i + 1 ] )
: ( $ref->[ $i + 1 ], $ref->[$i] );
$min = $current_min if ( $current_min < $min );
$max = $current_max if ( $current_max > $max );
$agv += $ref->[$i] + $ref->[ $i + 1 ];
$i += 2;
}
return ( $min, $max, $agv / @{$ref} );
}
__END__
s/iter op simple
op 1.13 -- -37%
simple 0.707 60% --
Next time I'll wait a bit more before coding :)
Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf
Don't fool yourself.
|