in reply to Re^2: Battle Royal Grep vs For
in thread Battle Royal Grep vs For
You're right, copying does take time, but I'm not sure that's really what's going on here. I tested some more myself.
use Benchmark qw( cmpthese ); my @input = ( 'x' x 100 ) x 1_000_000; sub copy_array { my @copy = @{$_[0]}; return @copy; } sub copy_grep { my @copy = grep /x/, @{$_[0]}; return @copy; } sub return_grep { return grep /x/, @{$_[0]}; } sub return_scalar_grep { return scalar grep /x/, @{$_[0]}; } sub bare_grep { grep /x/, @{$_[0]} } sub bare_scalar_grep { scalar grep /x/, @{$_[0]} } sub bare_list_grep { () = grep /x/, @{$_[0]} } cmpthese 100, { copy_array => sub { copy_array( \@inpu +t ) }, copy_grep => sub { copy_grep( \@inpu +t ) }, return_grep => sub { return_grep( \@inpu +t ) }, return_scalar_grep => sub { return_scalar_grep( \@inpu +t ) }, bare_grep => sub { bare_grep( \@inpu +t ) }, bare_scalar_grep => sub { bare_scalar_grep( \@inpu +t ) }, bare_list_grep => sub { bare_list_grep( \@inpu +t ) }, }; __END__ Rate copy_grep copy_array bare_list_grep return_s +calar_grep return_grep bare_scalar_grep bare_grep copy_grep 1.23/s -- -21% -39% + -78% -79% -79% -79% copy_array 1.56/s 27% -- -23% + -73% -73% -73% -74% bare_list_grep 2.02/s 65% 30% -- + -64% -65% -65% -66% return_scalar_grep 5.69/s 363% 265% 181% + -- -2% -2% -4% return_grep 5.78/s 371% 271% 185% + 2% -- -1% -3% bare_scalar_grep 5.82/s 374% 274% 188% + 2% 1% -- -2% bare_grep 5.93/s 383% 280% 193% + 4% 3% 2% --
What this is meant to show is really that grep performs differently depending on context.
Benchmark::cmpthese calls the subs you give it in void context, so if you want another context for your code, you need to provide it. This is part of why the subs I wrote are careful to actually collect (and return) results. That's what these would do in the real world.
In void context, grep doesn't bother to make a list, so it's a lot faster. It's also faster when I forced a scalar context because it again doesn't make a list. In that case, it just counts the matches and passes out the number. You can see that the void and scalar cases are far ahead of all the others.
The grep in list context without a copy is only slightly faster than the one that makes a copy. Basically it's in the ballpark of copying while all the others (in void and scalar contexts) are in another ballpark.
|
|---|