VMwareのFC6ゲストのCPU負荷が高い件について。
VMware Server 1.0.xを使っていて気がついたのだが、ゲストとして走らせるOSによってえらくホストのCPU Usageが違うようだ。ユーザープロセスをなるべく動作させない状態でホスト上のtopコマンドで観察していると、Ubuntu 6.10 ServerのCPU Usageは1%未満、Fedora Core 6は5%程度になる。ラフに見積もってFedora Coreの方が5倍以上負荷が高いことになる。ちょっと気になったので調べてみた。
結論から言うと、Ubuntu 6.10 Serverではカーネルコンパイル時のCONFIG_HZの値が100、Fedora Core 6では1000になっている。さらに、kernel.orgからダウンロードしてきたカーネルソースを読んでみると、デフォルトは250になっていて100, 250, 1000の3種類から選べるようになっていた。ざらっとソースを眺めてみたところによると、結局この値はタイマー割り込みの頻度の多寡を制御する結果をもたらすことになるようだ(OleのTalkでトラップが50kHz以上の頻度で発生する、と言っていた理由が今更ながら分かった)。この値が大きいほど割り込み頻度が高まるのでデスクトップシステムに適合するし、小さいほどユーザコードを効率良く実行してくれるのでサーバシステムに適合する。だから、デスクトップパッケージであるFedora Coreには1000、サーバパッケージであるUbuntu Serverには100が設定されているのだろう。
一方でVMware ServerではネイティブOSに比べてコンテキストスイッチとカーネルモードの実行オーバーヘッドが大きい。つまりは、割り込み頻度が高ければ高いほど(ユーザモードのワークロードに関わらず)VMwareのソフトウェアオーバーヘッドはより大きくなり、CPU Usageの差となって現れるのだろう。
何となく原因にあたりが付いたところで、この値を変更できないものかと思った。ソースを斜め読みした限りではブート時のカーネルオプションでは制御できない。タイマーはごくクリティカルな処理なのでカーネル変数を取得して計算するよりはCONFIG_HZの値をインライン展開しておきたいと考えるのはカーネル設計者としては当然のことだ。マルチバージョニングする手もあるけどね。
しかたがないのでFC6のカーネルをCONFIG_HZ=250で再構築してみて確認してみることにした(Ubuntu Desktopは250だから250でいいじゃんかという発想)。Linuxのカーネルなんてかれこれ10年はmakeしていないのでいろいろ試行錯誤した結果、以下のような手順でOKらしいことが分かった。
まず、root権限でいろいろ入れておく。
# yum install yum-utils rpmdevtools unidef
次にユーザ権限でビルドするための環境を作る。
$ cd ~ $ rpmdev-setuptree $ rpm -Uvh http://ftp.riken.jp/Linux/fedora/core/updates/6/SRPMS/kernel-2.6.19-1.2911.6.5.fc6.src.rpm $ cd ~/rpmbuild/SPECS $ rpmbuild -bp --target `uname -m` kernel-2.6.spec $ cd ~/rpmbuild/BUILD/kernel-2.6.19/linux-2.6.19.x86_64 $ cp configs/kernel-2.6.19-x86_64.config .config
次に.configを編集する。make menuconfigして編集してもいいが面倒くさいのでviを使って変更すればよい。
@@ -190,9 +189,9 @@ CONFIG_CC_STACKPROTECTOR=y # CONFIG_CC_STACKPROTECTOR_ALL is not set # CONFIG_HZ_100 is not set -# CONFIG_HZ_250 is not set -CONFIG_HZ_1000=y -CONFIG_HZ=1000 +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 CONFIG_REORDER=y CONFIG_K8_NB=y CONFIG_GENERIC_HARDIRQS=y
Makefileの先頭付近のEXTRAVERSIONの定義を変更しておく。変更しておかないとuname -rが2.6.19-prepとかいう名前になってどのバージョンの何のカーネルか分からなくなる。
EXTRAVERSION = -1.2911.6.5.fc6-250hz
makeして、
$ make bzImage && make modules
root権限でインストールして再起動。
# env INSTALL_MOD_STRIP=1 make modules_install # installkernel 2.6.19-1.2911.6.5.fc6-250hz arch/x86_64/boot/bzImage System.map # reboot
あとはgrubのメニューで新規に追加されたカーネルをロードする。問題なければあとで/boot/grub/grub.confのdefaultの値を適当に変更しておくとよい。
結果はというと、5%くらいあったCPU Usageが1~2%くらいまで下がった。時計が遅れるとかいった問題が起きていないところを見るとおそらく問題ないのだろう。というわけで実験終了。
Comments and Trackbacks