use List::Util qw( shuffle ); my @match_0 = gen_values( 0 ); my @match_25 = gen_values( 1/4 ); my @match_50 = gen_values( 1/2 ); my @match_75 = gen_values( 3/4 ); my @match_100 = gen_values( 1 ); sub gen_values { my $proportion = shift; my $count = 10_000; my $matching = $count * $proportion; my @out; push @out, gen_matching() while $matching-- > 0; push @out, gen_non_matching() while scalar @out < $count; return shuffle @out; } sub gen_matching { my $out = gen_non_matching(); substr( $out, rand length $out, 1 ) = 'x'; return $out; } sub gen_non_matching { my $out = ''; $out .= int rand 10 while length $out < 100; return $out; } use Benchmark qw( cmpthese ); cmpthese -2, { for_0 => sub { for_loop( \@match_0 ) }, for_25 => sub { for_loop( \@match_25 ) }, for_50 => sub { for_loop( \@match_50 ) }, for_75 => sub { for_loop( \@match_75 ) }, for_100 => sub { for_loop( \@match_100 ) }, grep_0 => sub { grep_loop( \@match_0 ) }, grep_25 => sub { grep_loop( \@match_25 ) }, grep_50 => sub { grep_loop( \@match_50 ) }, grep_75 => sub { grep_loop( \@match_75 ) }, grep_100 => sub { grep_loop( \@match_100 ) }, }; sub for_loop { my @values = @{shift()}; my @matches; for ( @values ) { push @matches, $_ if /x/; } return @matches; } sub grep_loop { my @values = @{shift()}; my @matches = grep /x/, @values; return @matches; } __END__ Rate grep_100 grep_75 for_100 grep_50 for_75 for_50 grep_25 for_25 for_0 grep_0 grep_100 81.9/s -- -11% -18% -20% -25% -30% -31% -36% -42% -43% grep_75 92.0/s 12% -- -8% -10% -15% -21% -22% -28% -34% -36% for_100 100.0/s 22% 9% -- -2% -8% -14% -15% -22% -29% -30% grep_50 102/s 25% 11% 2% -- -6% -12% -13% -20% -27% -29% for_75 108/s 32% 18% 9% 6% -- -7% -8% -15% -23% -25% for_50 117/s 42% 27% 17% 14% 7% -- -1% -9% -17% -19% grep_25 118/s 44% 28% 18% 15% 9% 1% -- -7% -16% -18% for_25 128/s 56% 39% 28% 25% 18% 9% 8% -- -9% -11% for_0 140/s 71% 52% 40% 37% 29% 20% 19% 10% -- -3% grep_0 144/s 76% 56% 44% 41% 33% 23% 22% 13% 3% --