木曜日, 1月 18, 2007

[Perl]Benchmarkモジュールの小ネタ

PPerlのベンチを取りたくて、timeコマンドとかでも充分差は出るのですが、繰り返し実行される際の差を取りたかったのでBenchmarkモジュールでやろうとしたら少しおかしな結果になりました。

ちなみにPPerlとはスクリプトをコンパイルしてデーモンとして常駐させることで、起動時のオーバーヘッドをなくして高速化するというモジュールです。これもPerl Hacksに載ってます。

ベンチ対象(hello.pl)

use strict;
use Template;

my $tmpl = <<__TMPL__;
str = [% str %]
__TMPL__

my $tt = Template->new();
$tt->process(\$tmpl, { str => 'hello' });

print "hello\n"だけでやるとプロセス間通信のオーバーヘッドの方が大きいのかかえって遅くなったので、適当に大きめなモジュールを使えということでTemplateを使用。

で、ベンチのプログラムですが、以下のようにSYNOPSISどおりに実行すると
#!/usr/local/bin/perl
use strict;
use Benchmark qw(timethese);

timethese(100, {
    pperl => sub {
        my $ret = `/usr/bin/pperl -w --no-cleanup hello.pl`;
        die "error" unless ($ret =~ m|hello|);
    },
    perl => sub {
        my $ret = `/usr/bin/perl -w hello.pl`;
        die "error" unless ($ret =~ m|hello|);
    },
});


こんな感じになります。
Benchmark: timing 100 iterations of perl, pperl...
    perl: 42 wallclock secs ( 0.01 usr 0.03 sys + 38.64 cusr 2.56 csys = 41.24 CPU) @ 2500.00/s (n=100)
    pperl: 6 wallclock secs ( 0.01 usr 0.03 sys + 0.34 cusr 0.38 csys = 0.76 CPU) @ 2500.00/s (n=100)


wallclockとかはちゃんと出ているんですがRateがおかしい。これでも結果はわかるといえばわかるのですが気にいらないのでいろいろ調べていると、第3引数にstyleを指定することができるというのを見つけました。これを使うと親プロセスだけの時間とか子プロセスだけの時間とか計ってくれるようです。今回は子プロセスの実行時間が欲しいので'nop'としました。

スタイルの指定
#!/usr/local/bin/perl
use strict;
use Benchmark qw(timethese :hireswallclock);

timethese(100, {
    pperl => sub {
        my $ret = `/usr/bin/pperl -w --no-cleanup hello.pl`;
        die "error" unless ($ret =~ m|hello|);
    },
    perl => sub {
        my $ret = `/usr/bin/perl -w hello.pl`;
        die "error" unless ($ret =~ m|hello|);
    },
}, 'nop');


実行結果
Benchmark: timing 100 iterations of perl, pperl...
    perl: 47.9732 wallclock secs (44.66 cusr + 3.14 csys = 47.80 CPU) @ 2.09/s (n=100)
    pperl: 7.10064 wallclock secs ( 0.35 cusr + 0.47 csys = 0.82 CPU) @ 121.95/s (n=100)

うまく出ました。それにしてもallのとき(デフォルト)は親子の合計で/sも出してくれればいいのにと思うのは私だけでしょうか?

ちなみにこれを調べている過程で':hireswallclock'を見つけました。これをuseのときに指定しておけばwallclockもTime::HiResで出してくれます。ちょっと便利。




0 件のコメント: