2008年04月30日(水) 09:25

PersistentPerl(SpeedyCGI)のメモ

PersistentPerl は Perlスクリプトをメモリに常駐させて起動時のオーバヘッドを軽減し、サーバ負荷やレスポンスを改善する。同じような機能の mod_perl ほどの効果はないようですが、導入が比較的楽そうなので、インストールから稼動までやってみました。

ちなみに、SpeedyCGI と PersistentPerl は同じもので、SpeedyCGI から PersistentPerl に名前が変わっただけと思っていいみたい。


試した環境

  • Vine Linux4.2
  • Kernel2.6.16
  • Apache1.3.41
  • Perl5.8.6
  • PersistentPerl2.22
  • gcc3.3.6


PersistentPerlインストール

CPANからインストール

cpan> install PersistentPerl


testでコケたので、無理矢理。

cpan> force install PersistentPerl


途中で、mod_persistentperl をインストールするか問い合わせがありますが、デフォルト no なので、そのままエンター押してスルーです(mod_persistentperl は Apache のモジュールで、インストールするには apxs コマンドにパスが通ってないとダメらしいです。今回は CGI で PersistentPerl を使うだけなので、mod_persistentperl は特にインストールせず)。


CPANでだめならソースからコンパイルしてインストール。

# wget http://www.cpan.org/modules/by-authors/id/H/HO/HORROCKS/PersistentPerl-2.22.tar.gz
# tar xvfz PersistentPerl-2.22.tar.gz
# cd PersistentPerl-2.22
# perl Makefile.PL
# make
# make test
# make install


OSによっては、バイナリがあったり、RPMがあったりするみたいですが、Vine Linuxでは見つからんかった(っつーか、あんま探してない)。


Perlスクリプトの編集

詳しいオプションなどは、後ほど公式ドキュメントを参照していただくとして、最低限、Perlスクリプトを PersistentPerl で利用するためには、以下の編集が必要になります。


スクリプト冒頭の Perlパスを以下のように書き換え。

#!/usr/bin/perl
  ↓↓↓
#!/usr/bin/perperl


なんと、たったこれだけでスクリプトがメモリに常駐してくれるようになり、サーバ負荷の軽減やレスポンス向上をもたらしてくれるのです。稼動の多いCGIスクリプトなんかでは重宝すると思います。


PersistentPerlのワナ

さて、すごく楽に導入できる PersistentPerl ですが、そこには当然ワナがあります。

Also, if you create global variables with ``my'', you shouldn't try to reference those variables from within a subroutine - you should pass them into the subroutine instead. Or better yet just declare global variables with ``use vars'' instead of ``my'' to avoid the problem altogether.

スクリプトがメモリに常駐して実行されるため、グローバル変数が破棄されないというルールがあり、これはスクリプトの書き方によってはひっかかります。特に、my によって初期化しているつもりのグローバル変数を、サブルーチンに明示的に渡さず使用している場合、おかしなことになります


例えば、以下のコードはクエリーを表示するだけですが、グローバル変数($q)をサブルーチンに明示的に受け渡さず、サブルーチン(put_q)内で直接参照して表示しています。


[test.cgi]

#!/usr/bin/perperl


use strict;


my $q = $ENV{'QUERY_STRING'}; # $q を my 宣言


&put_q;


exit;


sub put_q {
    print "Content-Type: text/html\n\n";
    print $q; # グローバルの $q を参照表示
}


これを、CGIとして実行すると、1回目は望み通りの出力となりますが、2回目からはクエリーに何を渡しても1回目の出力から変化がなくなります。


[1回目の実行]

http://www.exampl.com/test.cgi?hoge → 「hoge」と表示される


[2回目の実行]

http://www.exampl.com/test.cgi?fuga → 「hoge」と表示されてしまう(期待する結果は「fuga」)


use strict; も宣言して通っているのに、と不可思議な気がするかもしれません。
これは、グローバル変数として my で定義されている $q がサブルーチン内で参照されるとき、1回目の実行で作成された $q を参照していることから起こります。3回目以降実行されてもずっと1回目のものとなります(PersistentPerlが再起動されると再定義されますが、メモリに常駐している間は同じ)。


この現象は以下のように、明示的に変数を受け渡すことで回避できます。

#!/usr/bin/perperl


use strict;


my $q = $ENV{'QUERY_STRING'};


&put_q($q);


sub put_q {
    my $str = shift;
    print "Content-Type: text/html\n\n";
    print $str;
}


または、our(use vars qw($hoge);)で宣言することでも回避できます。

#!/usr/bin/perperl


use strict;


our $q = $ENV{'QUERY_STRING'};


&put_q;


sub put_q {
    print "Content-Type: text/html\n\n";
    print $q;
}


都度 実行するだけのCGIを書いているうちは、なんとか動くので気付きにくいですが、そういうことらしいです。
プログラミングの作法として覚えておこうと思う。


参考:PersistentPerl(英語) PersistentPerl2.21(和訳)

このエントリーに最初のコメントを書いてみませんか?

名前  クッキーに保存 
エントリーナビ
PersistentPerl(SpeedyCGI)のメモ」は、
Perl カテゴリーの記事です。


関連エントリー
PersistentPerl(SpeedyCGI)のチューニング
CPAN検索ブックマークレット
Perlの変数:多次元配列とかリファレンスとか
WebService::SimpleでAmazon Web API
ズキアカのチャンネー夙川アトム風変換ドーン!Text::MeCabメモ

トラックバック
このエントリーへトラックバックするURL (言及リンクのないトラックバックは無効です)