Apacheのチューニング

httpd.confに設定する最大接続数(MaxClients)とかをチューニングする場合、プロセスごとにどれくらいのメモリを使っているかを調べる必要がある。Linuxなら/proc/PID以下にその情報があるので、少し整形するスクリプトを書いてやれば調査が出来る。PerlのLinux::Smapsを使うとプログラマブルに書けるらしいけど、そもそもPerlを知らないし、あまり覚える気力も無いので、awkを使ってシェルスクリプトのみで書いてみた。

PIDを取得するときには

ps ax | grep -v grep | grep "process name"

みたいに書くのが常套句だと思ってたら、pgrepという便利な道具があったらしい。ほう。

注意事項

今回のスクリプトでは/proc/PID/statusと/proc/PID/smapsからデータを取ってきて、

/proc/PID/status
VmPeak
VmSize
VmHWM
VmRSS
/proc/PID/smaps
Rss
Shared_Clean
Shared_Dirty

をフィルターしている。これが存在するのは、主に2.6系列のカーネルなので、2.4系列の古いカーネルだと、以下のスクリプトはまともに動作しない。詳しくはmanページを参照。

プロセスごとのメモリ使用量を調べる

getmem.sh
#!/bin/sh
#1 process name
if [ $# -ne 1 ]; then
exit
fi
# print header
printf "PID\tVmPeak\tVmSize\tVmHWM\tVmRSS\n"
# get memory size
pid=`pgrep $1`
for p in $pid
do
if [ -f /proc/$p/status ]; then
vm=`grep -e '^VmPeak:\|VmSize:\|VmHWM:\|VmRSS:' /proc/$p/status | awk '{print $2}'`
printf "%d\t%d\t%d\t%d\t%d\n" $p $vm
fi
done

プロセス間で共有されているメモリ使用量を調べる

getshmem.sh
#!/bin/sh
# $1 process name
if [ $# -ne 1 ]; then
exit
fi
# print header
printf "PID\tRSS\tSHARED\n"
# get shared memory size
pid=`pgrep $1`
for p in $pid
do
if [ -f /proc/$p/smaps ]; then
vm=`grep -e '^Rss:\|^Shared_Clean:\|^Shared_Dirty:' /proc/$p/smaps |
awk '
BEGIN {
rss = 0;
clean = 0;
dirty = 0;
}
{
if($1 == "Rss:") {
rss += $2;
}
else if($1 == "Shared_Clean:") {
clean += $2;
}
else if($1 == "Shared_Dirty:") {
dirty += $2;
}
}
END {
per = (rss == 0) ? 0 : (clean+dirty)*100/rss;
printf("%d\t%d\t%d\n", rss, clean+dirty, per);
}
'`
printf "%d\t%d\t%d (%d%%)\n" $p $vm
fi
done