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) (...) は構文エラーになる。
ああしかし,バグレポートが面倒くさいなあ。