■
先日、作成中のCatalystアプリにおいてメモリリークが観測されました。
原因は、
use Template::Plugin; use base qw(Template::Plugin); sub new { my ($class, $context, $args) = @_; my $self = { _CONTEXT => $context, _STASH => $context->stash, }; bless $self , $class; }
としているところの、
_STASH => $context->stash
の部分で循環参照となってしまい、リークを起してしまったようです。
この問題によって、Catalyst::View::TTの、sub renderでの $tt->process()
で作成された$output(=画面に出力すべきHTML)が、
リクエスト終了後も開放されず、蓄積されていってしまったのでした。
循環参照の詳しい状況は再度追って報告します。
GTop
今回はGTopモジュールでメモリの推移を把握し、
ボトルネックを突き止めるアプローチを行ないました。
MyApp.pmに以下を追加します。
use GTop; sub prepare { my ( $class, $args) = @_; my $gtop = GTop->new; my $memory_in_start = $gtop->mem($$)->size; my $c = $class->Super::prepare( $args ); $c->stash->{gtop} = $gtop; $c->stash->{memory_in_start} = $memory_in_start; return $c; } sub finalize_body { my ( $class, $c ) = @_; $class->Super::finalize_body( $c ); $c->stash->{memory_in_end} = $c->stash->{gtop}->mem($$)->size; $c->log->debug( "Diff:" . GTop::size( $c->stash->{memory_in_end} - $c->stash->{memory_in_start}) ); }
これで、リクエストに対する処理が終了するまでのメモリの推移が、ログに出力されます。