in reply to Re: Loops and speed
in thread Loops and speed

This Benchmark exhibits some of the same problems I discussed in Re: Re: Craftier. In particular, @foo is a lexical variable which is not accessible in the Benchmark package, where your code snippets are being compiled. All of your snippets are working on an empty @foo. (You might have noticed that, despite the three print statements, your code never actually printed anything.)

Since you're passing quoted strings, all you're really testing is the time to compile each snippet, which is not a very useful measure. Also note that the third snippet omitted $_ in the print statement.

Here's an improved benchmark.

#!/usr/local/bin/perl -w use strict; use Benchmark; my @foo = map {int rand 3} 1..100; open(OUT, ">bm.out") or die "$!\n"; # Note: bm.out will be a large file when this is done. :) timethese(-10, { mod => sub { for (@foo) { print OUT "$_" if $_; } print OUT "\n"; }, block => sub { for (@foo) { if ($_) { print OUT "$_"; } } print OUT "\n"; }, and => sub { for (@foo) { $_ and print OUT "$_"; } print OUT "\n"; }, } ); __END__ Benchmark: running and, block, mod, each for at least 10 CPU seconds.. +. and: 3554.42/s block: 3530.86/s mod: 3511.90/s
With a re-structured benchmark, all three options are roughly equivalent, as you would expect.

However, there's also a lot of extra code in each snippet, which could be obscuring actual differences between the code we're really trying to test. In particular, I'd expect the print to be slow relative to the rest of the code.

Here's another benchmark.

#!/usr/local/bin/perl -w use strict; use Benchmark; my $foo = 0; # $foo will be toggled between true and false my $x; timethese(-10, { mod => sub { $x = 1 if $foo ^= 1 }, block => sub { if ($foo ^= 1) { $x = 1 } }, and => sub { $foo ^= 1 and $x = 1 }, } ); __END__ Benchmark: running and, block, mod, each for at least 10 CPU seconds.. +. and: 233020.67/s block: 230307.69/s mod: 234463.20/s Benchmark: running and, block, mod, each for at least 10 CPU seconds.. +. and: 237002.40/s block: 236647.46/s mod: 226841.12/s
This benchmark also shows no significant difference between the three forms.

We can draw two conclusions from these results: first, that it is important to have a well-constructed benchmark; and second, that the three forms of if/then are equivalent in terms of efficiency.