MojoのGETパラメータの扱いでベンチに影響が出た件

※ 2010/9/26 追記
最新版とのベンチマーク比較
http://d.hatena.ne.jp/tori243/20100927/1285594260


※ 2010/9/15 追記
Mojoはまだβ版で、現在は安定稼働を優先に開発が進められているそうです。
最適化フェーズはその後のようなので
いずれはこのような問題も解消されていくと思われます。






現在サービスインしてるMojoliciousアプリのパフォーマンスがなかなか上がらんなーと数日がんばったのですが、
結局、単にサーバがついていけてないだけかなーという結論になった。


現状Mojoliciousを載っけてるwebサーバは某クラウドの一番下のモデルで
CPUが1GHzでメモリ512Mというやつなんですが、
MojoのGETパラメータが増えたり、MojoX::Dispatcher::Routes::Controller::paramsを使ったりすると
パフォーマンスがかなり劣化してしまうことが判明。


最初はMojoの問題なのかなーとも思ったけど
サーバ見てたらCPUバウンドなのでそもそも性能限界なのかな?

Mojoliciousバージョン

Mojolicious-0.999926

abベンチマーク

Mojoのヘルパーで作成されるExample.pmに、パラメータを操作するサブルーチンを追加。
以下ソースコードベンチマークを比較してみた。

  • welcome(ヘルパで勝手に作成されるサブルーチン)
  • welcome_tohash(GETパラメータを一度ハッシュに展開してから利用)
  • welcome_param(GETパラメータを直で利用)


ソースコード

package myapp::Example;

use strict;
use warnings;

use base 'Mojolicious::Controller';

# This action will render a template
sub welcome {
    my $self = shift;

    # Render template "example/welcome.html.ep" with message
    $self->render(message => 'Welcome to the Mojolicious Web Framework!');
}

sub welcome_tohash {
    my $self = shift;

    my $param_hash = $self->req->query_params->to_hash;
    $self->hoge(
        $param_hash->{'a'}||"",    
        $param_hash->{'b'}||"",    
        $param_hash->{'c'}||"",    
        $param_hash->{'d'}||"",    
        $param_hash->{'e'}||"",    
        $param_hash->{'f'}||"",    
        $param_hash->{'g'}||"",    
        $param_hash->{'h'}||"",    
        $param_hash->{'i'}||"",    
        $param_hash->{'j'}||"",    
        $param_hash->{'k'}||"",    
        $param_hash->{'l'}||"",    
        $param_hash->{'m'}||"",    
        $param_hash->{'n'}||"",    
    );
}

sub welcome_param {
    my $self = shift;
    $self->hoge(
        $self->param('a')||"",    
        $self->param('b')||"",    
        $self->param('c')||"",    
        $self->param('d')||"",    
        $self->param('e')||"",    
        $self->param('f')||"",    
        $self->param('g')||"",    
        $self->param('h')||"",    
        $self->param('i')||"",    
        $self->param('j')||"",    
        $self->param('k')||"",    
        $self->param('l')||"",    
        $self->param('m')||"",    
        $self->param('n')||"",    
    );
}

sub hoge {
    my $self = shift;
    my $message = @_;
    $self->render(template => 'example/welcome', message => 'Welcome Param! '. join(':', @_));
}

ベンチマーク結果

デフォルト:パラメータなし

/usr/local/apache2/bin/ab -n 500 -c 3 'http://xxxxxxx/example/welcome'

結果(平均値)

Requests per second = 100 [#/sec] (mean)


デフォルト:パラメータあり

/usr/local/apache2/bin/ab -n 500 -c 3 'http://xxxxxxx/example/welcome?a=aaa&b=bbb&c=ccc&d=ddd&e=eee&f=fff&g=ggg&h=hhh&i=iii&j=jjj&k=kkk&l=lll&m=mmm&n=nnn'

結果(平均値)

Requests per second = 60 [#/sec] (mean)


welcome_tohash:パラメータあり

/usr/local/apache2/bin/ab -n 500 -c 3 'http://xxxxxxx/service/example/welcome_tohash?a=aaa&b=bbb&c=ccc&d=ddd&e=eee&f=fff&g=ggg&h=hhh&i=iii&j=jjj&k=kkk&l=lll&m=mmm&n=nnn'

結果(平均値)

Requests per second = 35 [#/sec] (mean)


welcome_param:パラメータあり

/usr/local/apache2/bin/ab -n 500 -c 3 'http://xxxxxxx/service/example/welcome_param?a=aaa&b=bbb&c=ccc&d=ddd&e=eee&f=fff&g=ggg&h=hhh&i=iii&j=jjj&k=kkk&l=lll&m=mmm&n=nnn'

結果(平均値)

Requests per second = 16 [#/sec] (mean)

雑記

サーバの性能限界かもしれないけど
GETパラメータを付ける付けないでここまで差が出ることにびっくりしただけです><
WAF選定間違えたかなー