めも帖

「めも帖」代わりにダラダラと書いていったり、めもしたりしているだけです。

CGI.pmのインスタンス化は負荷が高い?

CGI.pmをインスタンス化するのって、実は負荷が高い?
ベンチマークをとっていると、CGI.pmをインスタンス化するだけで、あっという間に負荷が高くなるんですよねぇ。値を受け取ったりするだけであれば使わないほうがいいのかな?
試しに、インスタンス化するだけのCGIを実行。


#!/usr/local/bin/perl
use strict;
use CGI;
print "Content-type: text/html\n\n";
Benchmark::timethese(10000, { faq => \&test, });
sub test{
my $query = CGI->new;
}

で、結果は

Benchmark: timing 10000 iterations of faq... faq: 10 wallclock secs
( 4.44 usr + 0.00 sys = 4.44 CPU) @ 2252.25/s (n=10000)

となります。これ、結構負荷が高いと思います。見た目ですけれど(単に反応が遅い、というだけで高負荷としています)。
じゃあ、環境変数でメソッドを取得してみます。

#!/usr/local/bin/perl
use strict;
use CGI;
print "Content-type: text/html\n\n";
Benchmark::timethese(10000, { faq => \&test, });
sub test{
my $method = $ENV{'REQUEST_METHOD'};
}

で、結果は

Benchmark: timing 10000 iterations of faq... faq: 0 wallclock secs
( 0.02 usr + 0.00 sys = 0.02 CPU) @ 500000.00/s (n=10000) (warning: too few iterations for a reliable count)

瞬時に出ます。もちろん命令内容が違うとしても、これだけ違うと、CGI.pmを使うのをCGIでは1回だけとかに限る必要があるのかもしれません。なんども値の受け渡しごとに、CGI.pmを使用するPerlでのCGIは動作が鈍い可能性がある、と考えてみたりしました。

追記:
で、CGI.pmを使う方法と、使わない方法で同じ処理を書いてみたら、10倍早かった。CGIの場合、オブジェクト指向で作る個所と、そうでない個所を分けたほうがいいのかも?


逆に mod_perl 環境下で動作させることができない場合は、OO 実装によるオーバーヘッドを回避することができないためしんどい、ということになります。が、これもある程度の回避方法があります。起動時に極力最低限のクラスのみロードしておき、あとは必要になったところで動的にロードする、という方法です。具体的には、最低限のクラスはスクリプト先頭で use でロードして、それ以外はメソッドの中などで require や eval & use により呼び出す、という方法です。

とあるとおりなのかなあ、と。ここで気になるのは、useよりrequireの方が負荷が低いの?ということです。ここらへんは、また調べてみようと思います。