Perl のアクセサモジュールとしては、Class::Accessor::Fast が人気すね。
# これは例
package Hoge;
use base 'Class::Accessor::Fast';
__PACKAGE__->mk_accessors(qw( req ));
sub new {
my $class = shift;
bless {
url => 'http://e8y.net/',
req => HTTP::Request->new,
}, $class;
}
こんな風な、ハッシュに bless するよくあるクラスの場合に、そのハッシュのキーと同じ名前でgetterを作成しておくと、属性にアクセスする場合($hoge->url)と属性のオブジェクトのメソッドを呼ぶ場合($hoge->req->header())に、ブレース{} が途中に入ってこないので見やすいし、それが値なのかメソッドなのかを隠蔽してしまえてよい感じ。Class::Accessor::Fastはそれを簡単に作成できる。
もちろんアクセサ生成みたいなクラスユーティリティー的なモジュールは CPAN に五万とあります。その中の一つ、Class::Data::Accessor がアップデート(v0.03)されて、mk_classaccessors (複数形)メソッドが追加されているのを昨日知りました。
今までは mk_classaccessor (単数)しかなかったので論外だったのですが、気になったのでこの機会に Class::Accessor::Fast と同等のことができる既存アクセサモジュールをしらべてみることに。
$hoge->directory =~ s/\W+//; とかもできちゃう。mk_accessors() 宣言をいらなくしたバージョン。AUTOLOADなのでイマイチベンチマーク用のコードは↓に置いてあります。
http://e8y.net/repos/class-accessor-test/
結果発表!
Benchmark: timing 100000 iterations of Assert, Auto, CA, Data, Deep, Fast, Lvalue, LvalueFast, Normal...
Assert: 9 wallclock secs ( 8.69 usr + 0.00 sys = 8.69 CPU) @ 11507.48/s (n=100000)
Auto: 3 wallclock secs ( 2.80 usr + 0.00 sys = 2.80 CPU) @ 35714.29/s (n=100000)
CA: 4 wallclock secs ( 3.29 usr + 0.00 sys = 3.29 CPU) @ 30395.14/s (n=100000)
Data: 2 wallclock secs ( 2.60 usr + 0.00 sys = 2.60 CPU) @ 38461.54/s (n=100000)
Deep: 8 wallclock secs ( 8.38 usr + 0.00 sys = 8.38 CPU) @ 11933.17/s (n=100000)
Fast: 2 wallclock secs ( 2.30 usr + 0.00 sys = 2.30 CPU) @ 43478.26/s (n=100000)
Lvalue: 8 wallclock secs ( 9.61 usr + 0.00 sys = 9.61 CPU) @ 10405.83/s (n=100000)
LvalueFast: 3 wallclock secs ( 2.21 usr + 0.00 sys = 2.21 CPU) @ 45248.87/s (n=100000)
Normal: 1 wallclock secs ( 1.27 usr + 0.01 sys = 1.28 CPU) @ 78125.00/s (n=100000)
Rate Lvalue Assert Deep CA Auto Data Fast LvalueFast Normal
Lvalue 10406/s -- -10% -13% -66% -71% -73% -76% -77% -87%
Assert 11507/s 11% -- -4% -62% -68% -70% -74% -75% -85%
Deep 11933/s 15% 4% -- -61% -67% -69% -73% -74% -85%
CA 30395/s 192% 164% 155% -- -15% -21% -30% -33% -61%
Auto 35714/s 243% 210% 199% 18% -- -7% -18% -21% -54%
Data 38462/s 270% 234% 222% 27% 8% -- -12% -15% -51%
Fast 43478/s 318% 278% 264% 43% 22% 13% -- -4% -44%
LvalueFast 45249/s 335% 293% 279% 49% 27% 18% 4% -- -42%
Normal 78125/s 651% 579% 555% 157% 119% 103% 80% 73% --
Class::Accessor::Lvalue がかなり遅いのは、Tieをしているからかな。いろいろなことをする Class::Accessor、Class::Accessor::Assert や AUTOLOADな奴らは思った通り遅めですね。
そもそも調べるきっかけになった Class::Data::Accessor は、まあまあ健闘。Class::Accessor::Fastは、Fastを名乗るだけあって速い。
これ調べて一番びっくりだったのは、Class::Accessor::Lvalue::Fast の意外な速さ。ていうか、速っ! Lvalueって付け足しな機能なので、AUTOLOAD並に遅いと思っていたのでおどろきです。