macro.pm v0.04
以前のmacro.pmではマクロをdo{ ... }で囲んで展開していたのだが,マクロの中身が+(...)に展開できそうなときは+(...)に展開するように最適化したらだいぶ速くなった。
以下はperl v5.8.5 built for i386-linux-thread-multiで計った結果。
$ perl -Mblib example/benchmark.pl macro/0.04 Benchmark: running do, eval, macro, sub for at least 1 CPU seconds... do: 1 wallclock secs ( 1.05 usr + 0.00 sys = 1.05 CPU) eval: 1 wallclock secs ( 1.05 usr + 0.00 sys = 1.05 CPU) macro: 2 wallclock secs ( 1.05 usr + 0.00 sys = 1.05 CPU) sub: 1 wallclock secs ( 1.13 usr + 0.00 sys = 1.13 CPU) Rate sub eval do macro sub 1081/s -- -16% -73% -79% eval 1279/s 18% -- -68% -75% do 3938/s 264% 208% -- -23% macro 5119/s 374% 300% 30% --
このdoが以前のマクロの速度に相当するので,v0.03より30%ほど高速になったようだ。
以下,ベンチマークコード。
#!perl -w use strict; use Benchmark qw(:all); sub add{ $_[0] + $_[1] } use macro::filter add => \&add; printf "macro/%s\n", macro->VERSION; my $n = 1000; cmpthese timethese -1 => { macro => sub{ my $sum = 0; for my $i (1 .. $n){ $sum = add($sum, $i); } }, sub => sub{ my $sum = 0; for my $i (1 .. $n){ $sum = &add($sum, $i); } }, do => sub{ my $sum = 0; for my $i (1 .. $n){ $sum = do{ $sum + $i }; } }, eval => sub{ my $sum = 0; for my $i (1 .. $n){ $sum = eval{ $sum + $i }; } }, }; __END__
しかし,この作業の過程でB::Deparseのバグに行く手を阻まれた!
$ perl -MO=Deparse,-p -e 'for my $a(1){}' foreach my($a) (1) { (); } -e syntax OK
"-p"は可能な限り括弧をつけるよう指示するオプションだが,その結果生じるforeach my($a) (...) は構文エラーになる。
ああしかし,バグレポートが面倒くさいなあ。