murawaki の雑記

はてなグループから移転してきました

Perl の switch は遅いのではないかという疑惑

Perl で Switch を使っていたら遅かったので hashref + anon sub に書き変えた。

そもそも普段は、プログラムの速度をそんなに気にしない。たまたま研究室で Devel::NYTProf が話題になっていたので、何となくこのプロファイラを走らせてみた。そうすると Switch が意外と遅かったというのが始まり。

Switch は switch/case 構文を実現するモジュール。Perl5 自体は switch/case 構文やそれに類するパターンマッチ構文を持っていないが、use Switch; とすると使えるようになる。

どうやってこれを実現しているのかと思って Switch.pm を眺めてみた。Filter::Util::Call を使ってソースコードをフィルタリングしている。私の目的のように単純な処理を実現するには何とも大がかり。

で、Switch の代わりに採用したのが hashref + anon sub。

switch ($val) {
    case 'ABC' { CODE }
    case 'DEF' { CODE }
}

のかわりに

{ 'ABC' => sub { CODE }, 'DEF' => sub { CODE } }->{$val}()

とした。*1case に文字列しか使わない場合はこの方が良い。可読性もそれほど損なわれていないと個人的には思う。しかも、closure なので、switch と同じ様に、スコープの外側の変数が参照できる。

多分ここでベンチマークテストをやるべきなのだろう。でも面倒だからやらない。Devel::NYTProf の結果では、該当するサブルーチンの inclusive time が 1/3 になっていた。*2とりあえずは満足。

こちらにちょうど同じ様なコードが載っている。
http://blog.livedoor.jp/dankogai/archives/50423627.html

*1:Perl の Switch は fall-through ではない。

*2:別々の NYTProf の実行結果の比較は怪しい。同じコードの実行時間にもぶれがあるから。今回は、これだけ差がつけば明らか。