The SUPER pseudo class is very slow!
SUPER疑似クラスを通じたメソッド呼び出しは非常に遅い。
もしベースクラスに手を加えることができるなら,空のフックメソッドをベースクラスに仕込んでおくことを考えたほうがいいかもしれない。
たとえば以下のケース:
# using SUPER package BaseClass; sub new{ bless {}, shift } sub foo{ my($self) = @_; # do something } package DerivedClass; use parent -norequire => qw(BaseClass); sub pre_foo{ my($self) = @_; # do another thing } sub foo{ my($self) = @_; $self->pre_foo(); $self->SUPER::foo(); }
これは,以下のようにベースクラスのfoo()でpre_foo()を呼び出すようにしておき,サブクラスで拡張の余地を作っておくというコードでも全く同じ効果を持たせることができる。
# no SUPER package BaseClass; sub new{ bless {}, shift } sub pre_foo{ # empty hook } sub foo{ my($self) = @_; $self->pre_foo(); # do something } package DerivedClass; use parent -norequire => qw(BaseClass); sub pre_foo{ my($self) = @_; # do another thing }
もちろん,この書き換えにより,BaseClass->foo()そのものは内部でのメソッド呼び出しが増えて遅くなる。しかしDerivedClass->foo()を比較すると,圧倒的にこちらのバージョンのほうが高速である。
これは一つには,単純にメソッド呼び出し回数の違いもあるが,それ以上にSUPERメカニズム自体が非常に遅いということがある。
したがって,DerivedClassの使用が主であり,BaseClassに手を加えられるという状況なら,SUPERを使わないように書き換えるのは効果があると思われる。
Perl/5.10.0 on i686-linux Rate SUPER/D non-SUPER/D non-SUPER/B SUPER/B SUPER/D 27675/s -- -60% -69% -77% non-SUPER/D 68922/s 149% -- -22% -43% non-SUPER/B 88768/s 221% 29% -- -26% SUPER/B 120302/s 335% 75% 36% --
SUPER/B(Base)とnon-SUPER/Bを比較すると,SUPER/Baseのほうが40%速い。しかし,SUPER/D(Derived)とnon-SUPER/Dを比較すると,non-SUPER/Dのほうが162%速い。つまり,BaseとDerivedの使用率が五分五分ならば,non-SUPERに書き換える価値はあると思われる。