Svante
Svante

Reputation:

Perl: why is the if statement slower than "and"?

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?

Upvotes: 2

Views: 795

Answers (6)

ysth
ysth

Reputation: 98433

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

Upvotes: 17

runrig
runrig

Reputation: 6524

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.

Upvotes: 0

William Keller
William Keller

Reputation: 5410

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.

Upvotes: 2

DGM
DGM

Reputation: 26979

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. ;)

Upvotes: 11

shelfoo
shelfoo

Reputation: 1557

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)

Upvotes: 2

Leon Timmermans
Leon Timmermans

Reputation: 30245

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!

Upvotes: 10

Related Questions