Data::Util (Scalar::Util::Refから改名+α)
Data::Util
こんな汎用的な名前を付けてしまっていいのだろうかと思いつつリリース。
sv_derived_from()はもっと高速に実装できるはず,というアイデアを取り込んでみました*1。
use Data::Utilするときに-fast_isaオプションをつけると,UNIVERSAL::isaを高速版なバージョンで上書きします。高速版はUNIVERSAL::isaと比較するとこんな感じ。実行環境はPerl 5.8.5 on Linuxで,5.10以降だともう少しだけ速くなるはずです。
[Data-Util-0.02_01]$ perl -Mblib example/isa_bench.pl Benchmark: UNIVERSAL::isa vs. Data::Util::fast_isa For Foo=HASH(0x94ac538) Rate original fast_isa original 114688/s -- -32% fast_isa 168658/s 47% -- For Foo::X::X=HASH(0x95ba458) Rate original fast_isa original 84328/s -- -27% fast_isa 114975/s 36% -- For Unrelated=HASH(0x95bb2fc) Rate original fast_isa original 87061/s -- -29% fast_isa 122880/s 41% --
とまあ,けっこう速いです。
以下ベンチマークコード:
#!perl -w use strict; use Benchmark qw(:all); use Data::Util qw(neat); BEGIN{ *UNIVERSAL::fast_isa = \&Data::Util::fast_isa; } BEGIN{ package Base; sub new{ bless {} => shift; } package Foo; our @ISA = qw(Base); package Foo::X; our @ISA = qw(Foo); package Foo::X::X; our @ISA = qw(Foo::X); package Unrelated; our @ISA = qw(Base); } print "Perl $] on $^O\n"; print "Benchmark: UNIVERSAL::isa vs. Data::Util::fast_isa\n"; foreach my $x ( # qw(Foo Foo::X::X Unrelated), Foo->new, Foo::X::X->new, Unrelated->new){ print "\nFor ", neat($x), "\n"; cmpthese -1 => { 'original' => sub{ for(1 .. 10){ if($x->isa('Foo')){ ; } } }, 'fast_isa' => sub{ for(1 .. 10){ if($x->fast_isa('Foo')){ ; } } }, }; } __END__