普通、1つのサーバには複数のユーザが登録されています。 そのため、1つのサーバでは同時に複数の CGI プログラムが実行される可能性があります。共用サーバで、速度が遅くメモリを喰う CGI プログラムを動かすと すぐにマシンパワーが飽和してしまいます。 なるべく負荷のかからず実行速度が短い CGI プログラムを作らなければいけません。
ということを言い始めると、そもそも perl で CGI プログラムを書くこと自体 あまり お勧めできないのですが、perl を使いつつ なるべく負荷のかからない プログラムを書く方法を説明します。
ここでは掲示板を例にあげましょう。 掲示板というのは、発言回数よりも閲覧回数の方が圧倒的に多いものです。 例えばウチの掲示板を例にあげると、 1日あたり書き込みは 0〜3件程度ですが、閲覧は1日に100件以上あります。つまり、発言時に時間のかかる処理をしておき、閲覧時には ほとんど処理をしないようにしておけば、総合的にトータルの負荷を減らせます。
具体的に言うと、一番まずいのは
というものです。 これでは、発言時に軽い処理を、そして閲覧時に重い処理を行っていることになります。 閲覧回数は発言回数の100倍にもなるわけですから、 これは負荷の面では最悪の掲示板プログラムと言えるでしょう。
- 発言 (書き込み) する時は、ログの最後に発言を追加
- 閲覧 (読み込み) する時は、ログを全部読み込み、発言順を逆にして、新しいものから順に表示
一番負荷がかからない掲示板のタイプは、発言があるたびに HTML ファイルを生成するものです。 閲覧時には、web サーバが作成済の HTML を出力するだけなので、 CGI プログラムの起動などは一切行われません。しかし、一度作ってみるとわかるでしょうが、 発言時に HTML ファイルを生成してしまうため、 見栄えのカスタマイズが行いにくくなります。 書き込み時に生成される HTML の見栄えを変えようとしても、 以前に作成された HTML の見栄えは変わらないからです。
負荷を抑えようとすると見栄えのカスタマイズ性が損なわれてしまいます。 カスタマイズ性を上げようとするなら 実行時に HTML を生成する形が一番ですが、 これだと負荷がかかってしまいます。
これらの両立を目指したサンプルとして、 キャッシュと Last-Modifed ヘッダを使った例を後から示します。
C 言語を使う場合は、どれだけメモリを使用しているかを認識することができますし、 メモリ管理はプログラマの責任でもあります。 しかし perl では、メモリ確保を全て perl 側が行います。 これは perl の利点ではありますが、 その結果現在どれくらいメモリを喰っているかをプログラマが直観的に知るのは難しくなっています。 こういう点には できるだけ気を遣いましょう。
# 例1 open(IN,"file.txt"); @buf = <IN>; close(IN); foreach (@buf){ print $_; }これは、file.txt の内容全てを @buf に読み込んでしまいます。 file.txt が数十 KB 程度なら構いませんが、 数 MB、数十 MB になると、かなりの負荷がかかります。# 例2 open(IN,"file.txt"); while (<IN>){ print $_; } close(IN);これはファイルから 1行分を読み込んで 標準出力に書き出しています。先の例に比べると メモリ使用量はかなり抑えられるはずです。 しかし、さらによいのは# 例3 open(IN,"file.txt"); while (read(IN,$buf,8192)){ print $buf; } close(IN);です。例2 だと、もし1行がとてつもなく 長かったときにメモリを喰うからです。 例3 では、8192 バイトずつ読み込んで $buf に格納し、 標準出力に書き出しています。ちなみに、
# 例4 open(IN,"file.txt"); print <IN>; close(IN);は、ファイル内容全てをメモリに格納してから print してしまうので、 例1と同じくダメな書き方です。