Perl では、条件は次のいずれかで表現できます。
if (condition) { do something }
またはとして
(condition) and do { do something }
興味深いことに、2 番目の方法は約 10% 速いようです。誰かが理由を知っていますか?
Perl では、条件は次のいずれかで表現できます。
if (condition) { do something }
またはとして
(condition) and do { do something }
興味深いことに、2 番目の方法は約 10% 速いようです。誰かが理由を知っていますか?
以下のデパースに関するコメント:
まず、B::Terseを使用しないでください。廃止されました。B :: Conciseは、慣れればはるかに優れた情報を提供します。
次に、指定されたリテラルコードを使用して実行したため、条件はたまたま真のベアワードと見なされたため、どちらの場合もブールチェックが最適化され、目的が果たせなくなりました。
第3に、余分なオペコードはありません。「null」は、最適化されたオペコードを示します(完全に実行ツリーから外れていますが、解析ツリーには残っています)。
2つのケースの簡潔な実行ツリーは、次のとおりです。これらは同一であることが示されています。
$ 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
私はそれを逆解析しましたが、実際には速くなるべきではありません。最初のオペコード ツリーは次のとおりです。
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"
2 番目のオペコード ツリーは次のとおりです。
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"
後者がどのように高速になるかは本当にわかりません。オペコードをさらに実行します!
適切なコード プロファイリングを行う方法がわからない場合は、このようなことをしないでください。これら 2 つのメソッドの速度の違いは、同じ Big O() 速度内にあります (@Leon Timmermans オペコード分析で証明されているように) - ベンチマークは、必ずしもコードではなく、他のローカル条件に基づいて違いを示すだけです。
@Svante は「and」の方が速いと言い、@shelfoo は「if」の方が速いと言いました。
つまり、1000 万回のループで 700 分の 1 秒の変化ということですか? それは統計的に速くも遅くもありません....それは等しいです。
このようなごくわずかなタイミングを見る代わりに、コードのリファクタリングと Big O() 表記について学び、コード内のループの数を減らす方法と、コード プロファイラーを使用して実際のタイミングを確認する方法を学びます。ボトルネックは。統計的に意味のないものについて心配する必要はありません。;)
平均化する前に何回テストを行いましたか? 非常に小さな偏差は、統計的に重要ではありません! テスト間で速度がわずかに異なる理由はたくさんあります。
ベンチマークによると、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)
また、Perl のバージョンに依存する場合もあります。あなたが言及していないこと。とにかく、その違いは心配するほどではありません。したがって、より意味のあるものを使用してください。