In Perl, a conditional can be expressed either as
if (condition) { do something }
or as
(condition) and do { do something }
Interestingly, the second way seems to be about 10% faster. Does anyone know why?
In Perl, a conditional can be expressed either as
if (condition) { do something }
or as
(condition) and do { do something }
Interestingly, the second way seems to be about 10% faster. Does anyone know why?
I've deparsed it, and it really shouldn't be faster. The opcode tree for the first is
LISTOP (0x8177a18) leave [1]
OP (0x8176590) enter
COP (0x8177a40) nextstate
LISTOP (0x8177b20) scope
OP (0x81779b8) null [174]
UNOP (0x8177c40) dofile
SVOP (0x8177b58) const [1] PV (0x81546e4) "something"
The opcode tree for the second is
LISTOP (0x8177b28) leave [1]
OP (0x8176598) enter
COP (0x8177a48) nextstate
UNOP (0x8177980) null
LISTOP (0x8177ca0) scope
OP (0x81779c0) null [174]
UNOP (0x8177c48) dofile
SVOP (0x8177b60) const [1] PV (0x81546e4) "something"
I really don't see how the latter could be faster. It does an opcode more!
According to Benchmark, the second is slightly slower. Possibly it has something to do with the condition, but here's results for a very simple case:
use Benchmark;
timethese(10000000, {
'if' => '$m=5;if($m > 4){my $i=0;}',
'and' => '$m=5; $m > 4 and do {my $i =0}',
});
Results:
Benchmark: timing 10000000 iterations of Name1, Name2...
if: 3 wallclock secs ( 2.94 usr + 0.01 sys = 2.95 CPU) @ 3389830.51/s (n=10000000)
and: 3 wallclock secs ( 3.01 usr + 0.01 sys = 3.02 CPU) @ 3311258.28/s (n=10000000)
Which just goes to show, if you don't know how to do proper code profiling, don't be doing this stuff. The speed difference of these two methods are within the same Big O() speed (As proven by @Leon Timmermans opcode analyisis) - the benchmarks are just going to show differences based on other local conditions, not necessarily your code.
@Svante said the "and" was faster, and @shelfoo said "if" was faster.
I mean really... 7 hundredths of a second change for 10 million loops? That's not faster or slower, statistically.... that's equal.
Instead of looking at miniscule timings like this, learn about code refactoring and Big O() notation... how to reduce the number of loops in your code... and most of all, how to use code profilers to see where the real bottlenecks are. Don't worry about the statistically insignificant stuff. ;)
How many tests did you do before you averaged? Very, very small deviations are statistically insignificant! There are plenty of reasons for speed to vary slightly between tests.
Some comments about the deparse below:
First, don't use B::Terse, it's obsolete. B::Concise gives you much better information once you are used to it.
Second, you've run it using the literal code given, so condition was taken as a bareword that happens to be true, so the boolean check was optimized away in both cases, which kind of defeats the purpose.
Third, there isn't an extra opcode - the "null" indicates an opcode that's been optimized away (completely out of the execution tree, though still in the parse tree.)
Here's the Concise execution tree for the two cases, which shows them as identical:
$ perl -MO=Concise,-exec -e'($condition) and do { do something }'
1 <0> enter
2 <;> nextstate(main 2 -e:1) v
3 <#> gvsv[*condition] s
4 <|> and(other->5) vK/1
5 <$> const[PV "something"] s/BARE
6 <1> dofile vK/1
7 <@> leave[1 ref] vKP/REFC
-e syntax OK
$ perl -MO=Concise,-exec -e'if ($condition) { do something }'
1 <0> enter
2 <;> nextstate(main 3 -e:1) v
3 <#> gvsv[*condition] s
4 <|> and(other->5) vK/1
5 <$> const[PV "something"] s/BARE
6 <1> dofile vK/1
7 <@> leave[1 ref] vKP/REFC
-e syntax OK
It also could depend on the version of Perl. Which you haven't mentioned. And the difference is not enough to worry about anyway. So use whatever makes more sense.