Bulknews::Subtech RSSフィード

2009/02/08 (日)

メタプログラミングとevalのベンチマーク 06:58  メタプログラミングとevalのベンチマーク - Bulknews::Subtech を含むブックマーク はてなブックマーク -  メタプログラミングとevalのベンチマーク - Bulknews::Subtech

404 Blog Not Found:perl,javascript and more - evalは最後の武器

「evalは最後の武器」というのは、Perlに限らずメタプログラミング可能な言語における鉄則とも言える。たいていの場合、無名関数を生成するだけで同様の目的をより安全かつ高速に行えるのだ。

記事全体には同意するけど、「高速」という部分はどうだろ。Mooseは無名クラスの生成に無名関数ではなくて string eval を使ってクラスをコンパイルしてるんだけど、string eval のほうが実行時に速い、というのがひとつの理由だったとおもう。

こんな単純な例でも、30倍の速度差が出ている。

このコードは benchmark のループ内で毎回 eval を実行しているから、そもそも比較の対象としておかしい。


#!/usr/bin/perl                                                                                                         
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;

eval 'package FooEval; sub bar { $_[0] + $_[1] }';
*FooAnon::bar = sub { $_[0] + $_[1] };

cmpthese(
    timethese(
        0,
        {   
            eval => sub {
                FooEval::bar( 1, 1 ) == 2 or die;
            },
            anon => sub {
                FooAnon::bar( 1, 1 ) == 2 or die;
              }
        }
    )
);

実際のメタプログラミングの手法を考えると、まずこういう風に subref を eval をつかったほうほうとそうでない純粋な無名関数とでbenchmarkの外側で定義して実行時コストを比較すべき。

Benchmark: running anon, eval for at least 3 CPU seconds...
      anon:  4 wallclock secs ( 3.15 usr +  0.01 sys =  3.16 CPU) @ 1837367.09/s (n=5806080)
      eval:  4 wallclock secs ( 3.23 usr +  0.00 sys =  3.23 CPU) @ 1855530.03/s (n=5993362)
          Rate anon eval
anon 1837367/s   --  -1%
eval 1855530/s   1%   --

となってほとんど同じ。