2008/07/29(Tue)SpeedyCGIが大量起動

2008/07/29 0:47 Languages::Perl
このblogもそうだが、adiaryをサーバーに導入して、この公開blogと非公開blogを2つ運営している。
ごらんのとおり、このModus Operandiが公開blogである。
色々とadiary.conf.cgiの設定も違うから、ファイルを別個に分けてあるのだけど、どーも、moのほうだけ開くのが遅い。遅い。bf:遅い。
特にひどいのは記事をSubmitするときとか、管理メニューを開くとき。10秒くらい待たされることが多々。red:これはひどい。


何でだろうと思って、ターミナルを開くとこれまた重い。
Load Averageが5とか10とかになってやんの。どおりで重いわけだ……。

topをかけてみると、こんな感じ。*1
top - 00:51:48 up 88 days,  8:29,  1 user,  load average: 3.06, 2.15, 1.80
Tasks: 218 total,   5 running, 213 sleeping,   0 stopped,   0 zombie
Cpu(s): 98.5%us,  1.5%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    515212k total,   349296k used,   165916k free,     8944k buffers
Swap:   787176k total,   388272k used,   398904k free,    58780k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
18019 apache    20   0 30468  24m 2816 R 25.8  4.9   0:29.53 speedy_backend
17995 apache    20   0 29632  23m 2816 R 25.3  4.8   0:25.77 speedy_backend
18047 apache    20   0 28812  23m 2816 R 25.3  4.6   0:18.32 speedy_backend
17982 apache    20   0 28952  23m 2816 S 13.6  4.6   0:20.50 speedy_backend
18179 apache    20   0 25420  19m 2780 R  7.3  3.9   0:03.92 speedy_backend
 8566 apache    20   0  3912 1448 1444 S  0.0  0.3   0:00.01 speedy_backend
 8567 apache    20   0 25904 7580 2936 S  0.0  1.5   0:13.11 speedy_backend
16712 apache    20   0 26096 5728 2180 S  0.0  1.1   0:00.18 httpd
16719 apache    20   0 26100 5708 2176 S  0.0  1.1   0:00.13 httpd
17282 apache    20   0  3912 1832 1456 S  0.0  0.4   0:00.02 speedy_backend
17356 apache    20   0 26120 6804 3204 S  0.0  1.3   0:00.12 httpd
17647 apache    20   0 28352 9236 3216 S  0.0  1.8   0:00.66 httpd
18055 apache    20   0 26120 6784 3204 S  0.0  1.3   0:00.02 httpd
18155 apache    20   0  3640  800  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18158 apache    20   0  3640  804  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18159 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18160 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18161 apache    20   0  3640  796  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18162 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18163 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18164 apache    20   0 26096 5076 1552 S  0.0  1.0   0:00.01 httpd
18171 apache    20   0  3640  792  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18177 apache    20   0  3640  800  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18178 apache    20   0  3640  796  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18185 apache    20   0  3640  796  652 S  0.0  0.2   0:00.00 adiary.speedy.c
19629 apache    20   0 28716 7916 4552 S  0.0  1.5   0:05.22 httpd
19695 apache    20   0 28392 9724 4648 S  0.0  1.9   0:06.15 httpd
19726 apache    20   0 27052 7948 4444 S  0.0  1.5   0:03.95 httpd
19731 apache    20   0 28716 9468 4424 S  0.0  1.8   0:05.44 httpd
19744 apache    20   0 27940 9.9m 4720 S  0.0  2.0   0:04.48 httpd
19754 apache    20   0 27556 9748 4720 S  0.0  1.9   0:04.38 httpd
19760 apache    20   0 28376 9.8m 4608 S  0.0  2.0   0:06.34 httpd
19787 apache    20   0 27836 9.9m 4652 S  0.0  2.0   0:04.68 httpd
19813 apache    20   0 28696 9372 4296 S  0.0  1.8   0:05.04 httpd
22168 apache    20   0 28144 9284 4480 S  0.0  1.8   0:11.31 httpd
22170 apache    20   0 28136 8912 4624 S  0.0  1.7   0:08.38 httpd
22173 apache    20   0 27276 9036 4352 S  0.0  1.8   0:10.07 httpd
22175 apache    20   0 28720 8184 4648 S  0.0  1.6   0:14.24 httpd
26275 apache    20   0 28128 8724 4004 S  0.0  1.7   0:09.27 httpd
31115 apache    20   0 28708 9660 4476 S  0.0  1.9   0:09.31 httpd

apacheさんが大量にspeedyを起動しちゃって、backendが追いついていない感じ。
backendがアホみたいにCPUを食いつぶしているのが原因だろうと思って、一時的にspeedyの呼び出し引数に"-- -M5 -r10 -t3600"とか付けてみたんだけど、全然状況変わらず。


一方、非公開blogの方では同一バージョンを使用しているのに、全く
こういうことがない。speedyは常時2個くらい起動しっぱなしで、これ以上増えない。動作も快適。
が、moの方はリンクをクリックした拍子とかに10個も20個もバババーっと増えるのである。しばらくすると消える。

単にアクセス数の問題か……?否か……。
記事数ならば非公開blogの方がmoの10倍弱はある。


ちょっと時間ができたら双方を詳しく比べてこの問題を解決したいところである。今は時間がない。

*1 : 起動プロセス多すぎじゃね?とか、メモリが512MB(笑)とかいうのは置いといて……

2008/07/17(Thu)変数の展開の展開

2008/07/17 4:21 Languages::Perl
文字列処理にPerlほどすぐれた言語はない……と考えている今日この頃だが、ちょっとハマったので解決策をメモ。

やりたいこと

「何らかの処理の結果、ある文字列が得られたとする。その文字列と同じ名前の変数名を取得したい」

具体的には、リソースファイルに"この結果は$resultになります"のように埋め込んでおき、スクリプト実行時に変数$resultを代入して、"この結果は25になります"のように表示させたいわけだ。

今まで使っていた手法

リソースファイルをPerl化してしまってrequireすれば、同じ名前空間の変数で、すでに定義されているものは自動展開されるという仕様を使っていた。
埋め込む変数名ごとに正規表現で置換するような面倒な手法に比べると楽にできていたのだが、Perl化する手間とフォーマットが崩れるのが欠点。
拡張子がplになってしまうので*1、HTMLファイルのテンプレートを書いていたところで、vimなんかで読み込むとPerlの色づけしかしてくれなくて不便なのである。


実際どんな手順かというと、リソースファイルとして、
#!/usr/local/bin/perl

# requireされるとき自動展開するためにダブルクォートにしておく
$tmp = << "_EOM_";
この結果は$resultになります
_EOM_

# requireのため、1;は削除できない(結構面倒な仕様)
1;
という代入だけを行うスクリプトを別途用意し、
呼び出し側として、
#!/usr/local/bin/perl

$result = 5*5;
require 'resource.pl';
print $tmp;
のような手順を踏まなくてはいけない。自動展開されるとはいえ、結構めんどい。
また、$tmpや$resultという変数名は両ファイルで合わせておかなくてはならず、use strictとか付けると変数宣言の問題で面倒な事に。

*1 : そりゃ.htmlとか付けてもいいけど、中身perlだしね…不適切。

どうしたかというと

なんとか引数に指定した変数を展開できないかなぁと思って調べていたら、evalなんてコマンドがあった。
存在は知ってたけど、いまいち使いどころが分からなかったヤツ。

これを使うと実にスマートに書ける。
#!/usr/local/bin/perl

# シングルクォート囲みなのでこの時点では展開されないことに注意
$tmp = q|この結果は$resultになります|;
$result = 5*5;
$tmp =~ s/(\$\w+)/eval($1)/eg;
print $tmp.qq|\n|;
この書き方のポイントは、
  • $resultのような展開したい変数がいくつあっても動作すること
  • requireの必要がないこと = requireを使う場合の煩雑さがない
  • 展開する変数への代入を、読み込み後に行えること(requireの場合は、結果が先に分かってからrequireしないと代入されない)
  • (use strict環境下で小細工しなくても普通に動く)
注意として、↑のマッチングだと変数名のすぐ後に英数字が来ると誤爆するので、${result}のような形式のものだけ反応させるようにとか、適宜工夫することを推奨。