tokuhirom@株主の日記 このページをアンテナに追加 RSSフィード

2011-08-31

Xslate が SEGV したときにどうすればいいか 13:20 Xslate が SEGV したときにどうすればいいか - tokuhirom@株主の日記 を含むブックマーク

まず基礎知識として、Perl で webapp をかいている場合 SEGV する原因は

  • XSのバグ(80%)
  • 環境設定の問題(10%)
  • deep recursion で stack をつかいつくすなどの既知バグ(2%)
  • out of memory 系(1%)
  • Perl 本体のバグ(4%)

といったところです。(本体のバグについてはPerl 5.8 ではバグっていても 5.14 などではすでに修正されているバグも多いかとおもいます)。

というわけで、テンプレートエンジンがSEGVする場合のうち、90% はテンプレートエンジン自体の問題ではありません。そこでまずは SEGV する原因をしらべるわけですが、SEGV する原因をしらべるには、gdb をつかうのが簡単です。

% gdb --args perl `which plackup` app.psgi

などとして起動してから実際に SEGV をおとし、gdb がとまったところですかさず 'bt' コマンドをうちます(bt=backtrace)。この時、C レベルのスタックトレースがとれますが、このときに表示されているスタックトレースのログの一番上の方にのこっている部分に注目します。

今回の場合は Xslate の stacktrace ばかりが表示されていたので、あきらかに問題は xslate でした。他の XS モジュールの名前があらわれていた場合には xslate 以外が原因ですので、そちらをおってください。

問題があきらかになったらあとはコードをけずっていきます。base class の中身を問題の部分にむけてひきあげるとかそういうのを地道にやっていってどんどんコードをけずります。

最小のケースができあがったらあとは作者のふジゴロウにおくりつければそのうちなおります。

(このエントリー、途中でかいてるうちにめんどくさくなってしまいました)

2011-08-25

LWP::Protocol::PSGI のはなし 11:40 LWP::Protocol::PSGI のはなし - tokuhirom@株主の日記 を含むブックマーク

LWP::Protocol::PSGI をつかって HTTP の mocking とか簡単にできて便利だよね云々みたいな話かこうとおもったんだけどちょっとめんどくさくなりました。

2010-05-14

github におくだけで cpan にあがってないやつにおけるテストとか 05:32 github におくだけで cpan にあがってないやつにおけるテストとか - tokuhirom@株主の日記 を含むブックマーク

cpanm http://github.com/typester/net-github-upload-perl/tarball/master

とかできてすげー便利なのだが、これで xt/ のテストがこける。この場合、xt ははしらないべきか。

2010-05-08

最近いれてる chrome 拡張 04:21 最近いれてる chrome 拡張 - tokuhirom@株主の日記 を含むブックマーク

とか、そんなん。あんまりこったのはいれてない。

2010-05-07

Plack::Request#uri をキャッシュしつつ、ちゃんと expire もできる実装について考える 01:52 Plack::Request#uri をキャッシュしつつ、ちゃんと expire もできる実装について考える - tokuhirom@株主の日記 を含むブックマーク

Plack::Request の現在の実装では、uribase を一切キャッシュしておらず、これらのメソッドを多様すると、URI オブジェクトの生成コストが支配的となってしまうことがある(実際に、私のプロジェクトでこの問題が発生した)。

そこで、Variable::Magic を利用し、データの変更時にキャッシュを clear するようにしつつ、キャッシュをおこなうようにしてみた。

さて、いかがだろうか。なお、ベンチ結果はいかのとおり。

          Rate  orig  fast
orig   15582/s    --  -99%
fast 1048176/s 6627%    --
package Plack::Request::Cached;
use strict;
use warnings;
use parent qw/Plack::Request/;
use Variable::Magic qw/cast wizard VMG_OP_INFO_NAME/;
use Scalar::Util qw/refaddr weaken/;

our %MAP;

my $wiz = wizard(
    store => sub {
        delete $MAP{ refaddr( $_[0] ) }->{uri};
        delete $MAP{ refaddr( $_[0] ) }->{base};
    },
);

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    cast %{$self->env}, $wiz;
    my $addr = refaddr $self->env;
    $MAP{$addr} = $self;
    weaken($MAP{$addr});
    return $self;
}

sub DESTROY {
    my $self = shift;
    delete $MAP{refaddr $self->env};
}

sub uri {
    $_[0]->{uri} ||= do {
        my $self = shift;

        my $base = $self->_uri_base;

        my $path = $self->env->{PATH_INFO} || '';
        $path .= '?' . $self->env->{QUERY_STRING}
            if defined $self->env->{QUERY_STRING} && $self->env->{QUERY_STRING} ne '';

        $base =~ s!/$!! if $path =~ m!^/!;

        URI->new($base . $path)->canonical;
    };
}

sub base {
    $_[0]->{base} ||= do {
        my $self = shift;
        URI->new($self->_uri_base)->canonical;
    };
}

sub _uri_base {
    my $self = shift;

    my $env = $self->env;

    my $uri = ($env->{'psgi.url_scheme'} || "http") .
        "://" .
        ($env->{HTTP_HOST} || (($env->{SERVER_NAME} || "") . ":" . ($env->{SERVER_PORT} || 80))) .
        ($env->{SCRIPT_NAME} || '/');

    return $uri;
}

if ($0 eq __FILE__) {
    require Test::More;
    Test::More->import();
    {
        my $req = Plack::Request::Cached->new({HTTP_HOST => 'example.com'});
        is($req->uri, "http://example.com/");
        $req->env->{HTTP_HOST} = 'example.jp';
        is($req->uri, "http://example.jp/");
    }
    is(scalar(keys %MAP), 0);
    done_testing();

    require Benchmark;
    Benchmark->import(':all');

    my $req = Plack::Request->new({HTTP_HOST => 'example.com'});
    my $fast = Plack::Request::Cached->new({HTTP_HOST => 'example.com'});
    cmpthese(
        -1, {
            'orig' => sub {
                $req->uri;
            },
            'fast' => sub {
                $fast->uri;
            },
        },
    );
}

1;

ubuntu 10.04 LTS で、dvd みる 23:22 ubuntu 10.04 LTS で、dvd みる - tokuhirom@株主の日記 を含むブックマーク

sudo aptitude install vlc

してから、以下の URL にアクセスして、libdvdcss2 をいれる。

http://unofficial.debian-maintainers.org/

Plack::Request の uri/base が遅い件 21:59 Plack::Request の uri/base が遅い件 - tokuhirom@株主の日記 を含むブックマーク

まとめる時間がないんで、メモだけだが。

Plack::Request#uriPlack::Request#base をよびまくると、支配的になるぐらい遅い。

これは、Plack::Request#uriPlack::Reuqest#base も、一切キャッシュをしていないため。$req->env がかきかえられる可能性を考慮するとただしいのだが、ほとんどの場合はかきかえないとおもうし、自己責任でキャッシュできるような道筋が必要だとかんじた。

あるいは、なにかフックしてもいいのかもしらんけど。

URI->canonical は、必要ないケースも多いとおもうんで、それをオフにしたいというのもある。あれ遅い。

そもそも URIobject でもつ必要があるのかどうかという点もあって、id:kazuhookuあたりは、文字列でもてばいいじゃーん的なアレなんですが。