メモリリークを発見する
アプリケーションの規模が大きくなって、さまざまなオブジェクトを扱うようになってくると、オブジェクト間の循環参照やメモリリークする可能性も増えてきます。
循環参照、メモリリークをチェックするプラグイン
Catalystを使用したアプリケーションでもこれらの問題は発生しうるため、ここではCatalystX::LeakCheckerを使用したメモリリーク、循環参照を発見する方法を紹介します。
CatalystX::LeakCheckerをインストールするには、rootユーザで次のコマンドを実行します。
# perl -MCPAN -e 'install CatalystX::LeakChecker'
CatalystXネームスペースは、Catalystのモデル、ビュー、コントローラ、エンジンなどを拡張しない場合には、こちらのネームスペースを使用するように推奨されています。
CatalystX::LeakCheckerの例
CatalystX::LeakCheckerを使用するには、アプリケーションモジュールファイルで、次のように「with 'CatalystX::LeakChecker'」呼出を追加します。
package PluginSample1; use Moose; use namespace::autoclean; # 省略 extends 'Catalyst'; with 'CatalystX::LeakChecker';
これだけの設定で、リクエストごとにメモリリークなどのチェックが行われ、もしリークなどが存在すればログに出力されます。
例えば、次のようなアクションを定義してみましょう。
sub leak :Local {
my ( $self, $c ) = @_;
my %refs = ();
# 自分自身への参照を含むハッシュ
$refs{'self_refs'} = \%refs;
$c->stash->{refs} = \%refs;
$c->response->body('LeakChecker!');
}
このアクションを呼び出した場合には、次のようにログとしてレポートされます。
[info] Request took 0.052999s (18.868/s)
.------------------------------------------------------------+-----------.
| Action | Time |
+------------------------------------------------------------+-----------+
| /leak | 0.000650s |
| /end | 0.000869s |
'------------------------------------------------------------+-----------'
[debug] Circular reference detected:
.------------------------------------------------------------------------.
| $ctx->{stash}->{refs}->{self_refs} |
'------------------------------------------------------------------------'
CatalystX::LeakCheckerによるチェック処理はリクエストごとに行われるため、開発環境のみで確認を行い、プロダクション環境では必ず無効に設定するのを忘れないようにしましょう。
XML形式でデータを返す
Web APIなどのレスポンスとしてXML形式のデータを返さなければならない場合は、Ajaxや他システムとの連携でよく出てくるケースだと思いますが、このような場合に対応できるモジュールやプラグインは、たくさん用意されています。
オブジェクトを簡単にXML化して返す
ここでは、オブジェクトの配列やハッシュデータなどを簡単にXML化するビューモジュールである、Catalyst::View::REST::XMLを紹介します。
XMLのルート要素名が「response」に固定されているなど、いろいろと細かい部分をカスタマイズしたい場合には不向きかもしれませんが、手っ取り早くオブジェクトをXML形式に変換したい場合には便利に使うことができます。
Catalyst::View::REST::XMLをインストールするには、rootユーザーで次のコマンドを実行します。
# perl -MCPAN -e 'install Catalyst::View::REST::XML'
環境によっては、先に「XML::Simple」をインストールしておく必要があるかもしれません。
Catalyst::View::REST::XMLの例
まずはビューモジュールを作成してみましょう。「PluginSample1/lib/PluginSample1/View/REST.pm」というファイルを新規作成し、次の内容で保存します。
package PluginSample1::View::REST; use base qw( Catalyst::View::REST::XML); 1;
ここでは例として、名前と年齢を持つユーザー情報の配列をXML形式で返す方法を紹介します。ダミー情報を作成するメソッドでは、ハッシュに格納したユーザー情報を、配列に追加して返しています。
このユーザー情報をXML形式に変換するには、Stashに登録し「PluginSample1::View::REST」にforwardするだけです。
# ダミーデータ配列として返す
sub users {
my @users;
my %user1 = ('name'=>'Mako', 'age'=>33);
push @users, \%user1;
my %user2 = ('name'=>'Mayu', 'age'=>28);
push @users, \%user2;
my %user3 = ('name'=>'Shin', 'age'=>37);
push @users, \%user3;
my %user4 = ('name'=>'Yoshi', 'age'=>40);
push @users, \%user4;
return \@users;
}
sub xml :Local {
my ( $self, $c ) = @_;
$c->stash->{user} = $self->users();
$c->forward('View::REST');
}
このアクションを呼び出して得られるXML形式のレスポンスデータは次のようになります。
<response> <user name="Makoto" age="33" /> <user name="Mayu" age="28" /> <user name="Shin" age="37" /> <user name="Yoshi" age="40" /> </response>
ハッシュを入れ子にすれば、階層化したXMLとして出力することもできます。例えば住所情報として次のように表現することもできます。
<response>
<user name="Yoshi" age="40">
<address city="Shibuya" pref="Tokyo" />
</user>
</response>
