2

在 Perl 中,条件可以表示为

if (condition) { do something }

或作为

(condition) and do { do something }

有趣的是,第二种方式似乎快了大约 10%。有谁知道为什么?

4

6 回答 6

18

以下关于 deparse 的一些评论:

首先,不要使用 B::Terse,它已经过时了。B::Concise 一旦你习惯了它就会给你更好的信息。

其次,您已经使用给定的文字代码运行它,因此条件被视为碰巧为真的裸词,因此布尔检查在两种情况下都被优化掉了,这违背了目的。

第三,没有额外的操作码 - “null”表示已优化掉的操作码(完全在执行树之外,但仍在解析树中。)

这是这两种情况的简明执行树,显示它们相同:

$ 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
于 2008-09-18T09:18:35.200 回答
11

这只是表明,如果您不知道如何进行正确的代码分析,请不要做这些事情。这两种方法的速度差异在相同的 Big O() 速度范围内(正如@Leon Timmermans 操作码分析所证明的那样)——基准测试只会显示基于其他本地条件的差异,不一定是您的代码。

@Svante 说“and”更快,@shelfoo 说“if”更快。

我的意思是真的...... 1000 万次循环的百分之七秒变化?从统计学上讲,这不是更快或更慢……那是相等的。

与其查看像这样的微小时序,不如学习代码重构和大 O() 表示法……如何减少代码中的循环数……最重要的是,如何使用代码分析器来查看真正的瓶颈是。不要担心统计上微不足道的东西。;)

于 2008-09-18T03:52:07.700 回答
11

我已经对它进行了解析,它真的不应该更快。第一个操作码树是

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" 

第二个的操作码树是

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"

我真的不明白后者怎么会更快。它执行更多操作码!

于 2008-09-17T23:17:01.293 回答
3

在平均之前你做了多少测试?非常非常小的偏差在统计上是不显着的!速度在测试之间略有不同的原因有很多。

于 2008-09-18T03:55:06.133 回答
2

根据基准,第二个稍慢。可能它与条件有关,但这是一个非常简单的情况的结果:


use Benchmark;

timethese(10000000, {
    'if' => '$m=5;if($m > 4){my $i=0;}',
    'and' => '$m=5; $m > 4 and do {my $i =0}',
});

结果:


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)

于 2008-09-18T00:35:39.717 回答
0

它也可能取决于 Perl 的版本。你没有提到的。无论如何,差异不足以担心。所以使用任何更有意义的东西。

于 2008-09-18T15:34:33.173 回答