取势 明道 优术

作者为 扶 凯 发表

我一直使用 Feersum  做 Plack 的后端服务器,因为其性能实在太好了。以前我在开发我自己的视频调度器的时候发现我程序写好后性能并没达到我想象。后来根据排除替换大法, 查到是因为做 url 的参数解析的时候给 QUERY_STRING 字段取出来这段性能非常非常差, 基本会影响到 10-30% 的处理能力。
所以当时我自己的解决方法如下, 我自己直接取 $env->{'QUERY_STRING'} 的变量自己做了个简单的解析成键值对,这个功能并不使用原生的 Plack::Request 提供的接口。这样性能就能好非常非常多。

    my $query_string = $env->{QUERY_STRING};

    my %param;
    if ($query_string) {
        %param = map { split("=", $_, 2) } split("&",$query_string);
    }  

但这样解决其实是有小 bug 的,但基本不影响使用。性能也非常好,所以一直坚持到了现在。今天刚好看日本的 lestrrat 的 blog 时见到他也发现了同样的问题,并提出了更加好的解决方案。
他是使用 URL::Encode::XS 来做参数解析,然后存到 Hash::MultiValue 中。这样因为最麻烦的解析是换成了 URL::Encode::XS 性能好了很多。

use Plack::Request;
use URL::Encode; # URL::Encode::XSを入れておく事

{
    no strict 'refs';
    *Plack::Request::query_parameters = sub {
        my $self = shift;
        my $env = $self->env;
        my $query = $env->{'plack.request.query'};
        if ($query) {
            return $query;
        }
        $env->{'plack.request.query'} =
            Hash::MultiValue->new(@{URL::Encode::url_params_flat($env->{'QUERY_STRING'})});
    };
} 

我给我的程序的部分代码也修改成这样处理,发现性能比原来好多了,性能的影响小于 10% ,如果大家使用 Plack::Request 提供的接口,性能不好,可能就是因为这个原因,可以多多注意。
目前  lestrrat 给这个问题在 12 天前提交给 miyagawa 了,我想很快这个模块本身就会性能变得非常好了。
ps: 刚查了一下,最新的 Plack 都修复完了这个问题,性能得到了提升了。

来了就留个评论吧! 没有评论