How fast Mouse-XS in applications

v0.40_06から,Mouseが生成するコンストラクタとデストラクタもXSになった。Mouseが生成するアクセサはすでにXS化しているので,かなりのパフォーマンスが期待できるようになったはずだ。
しかし,いくらコンストラクタやアクセサといった部品が速くても,アプリケーションが高速にならなければ意味がない。
そこで,Any::Mooseを使ったモジュールであるHTTP::Engineで,PP版とXS版の速度差を比較してみた。

結果:

Perl/5.10.1 (i686-linux)
load HTTP::Engine, new(), and run()
     Rate   PP   XS
PP  789/s   -- -55%
XS 1748/s 122%   --
load HTTP::Engine, new(), and run() * 100
     Rate   PP   XS
PP 16.7/s   -- -20%
XS 20.8/s  25%   --

最初の結果は,ロード,new, runを単に行うコードで,CGIやテストスクリプトなどの非永続環境を模した状況における速度差であり,二番目の結果は,ロード,newの後に100回コードを実行するコードで,永続環境を模した状況における速度差である。

この結果によれば,まず非永続環境での速度差が著しく,XS版はPP版より約100%高速である。また,永続環境でも効果はあり,約20%高速である。これくらい差が出れば,苦労してXS化した甲斐があるといえる。

スクリプト

#!perl -w
use strict;
use Config; printf "Perl/%vd (%s)\n", $^V, $Config{archname};

use Benchmark qw(:hireswallclock);
use Benchmark::Forking qw(cmpthese);

use Encode (); # pre-load for Interface::Test
use HTTP::Request ();

sub new_he{
    my($use_pp) = @_;
    $ENV{MOUSE_PUREPERL} = $use_pp;

    require HTTP::Engine;

    return HTTP::Engine->new(
        interface       => {
            module => 'Test',
            request_handler => sub {
                my($request) = @_;

                return HTTP::Engine::Response->new(body => "Hello, world!\n");
            },
        },
    );
}

my $req = HTTP::Request->new(GET => 'http://localhost/');

print "load HTTP::Engine, new(), and run()\n";
cmpthese -1 => {
     'XS' => sub {
        my $he  = new_he(0);
        $he->run($req, env => \%ENV);
     },
     'PP' => sub {
        my $he  = new_he(1);
        $he->run($req, env => \%ENV);
     },
};

print "load HTTP::Engine, new(), and run() * 100\n";
cmpthese -1 => {
     'XS' => sub {
        my $he  = new_he(0);
        $he->run($req, env => \%ENV) for 1 .. 100;
     },
     'PP' => sub {
        my $he = new_he(1);
        $he->run($req, env => \%ENV) for 1 .. 100;
     },
};
__END__

ところで,今回はBenchmark::Forkingを使ってみた。これはベンチマークコンポーネント毎に別のプロセス空間で実行するため,今回のようなケースに適している。