2014年1月14日火曜日

kworkerのCPU過負荷

デスクトップを録画中にCPU90%以上の高負荷に見舞われた。数分間ディスクアクセスが続きその間はキーボードもマウスも受け付けない。LVMで2台目のHDをくっつけた数日後のことだったのでパフォーマンスが下がったのかと思っていたのだが、単なるディスク書き込みならI/Oをすべて奪い取るようなことはない。いつこれがはじまったのか記憶は曖昧だがカーネル3.8.0-33からだったかもしれない。

4コア中の1個目のコアのみに負荷がかかっているので、起動しているいずれかのプロセスの1個の特定のスレッドだけがCPUを使い果たしているのではないかと考えた。

ところがプロセスリストを見ると [kworker] なるプロセスが12個ほど発生していて、普段はOS起動時にちらっと1個だけ存在する極めて控えめなやつのはずだったものが、ここに来てオラオラ邪魔だどけ的に振る舞い始めている。頭にカーネルのkバッジを掲げる官憲みたいなプロセスの正体はほとんど知らなかった。topやiotopを見てもどのプロセスが呼んでいるかはわからない。実体がわかる名前くらい書いてもらいたいものだが。


フォーラムで調べてみるとかなり前から観察されている現象らしい。というか2年前から未解決のままかよ。

要約すると:

http://askubuntu.com/questions/176565/why-does-kworker-cpu-usage-get-so-high

共通の症状は、CPUの動作は通常通りで1つめのCPUコアだけが高負荷になっているところ。たとえば3つあるプロセスのうち2つが kworker で1つは gonem-system-mo である(topコマンドリストに出てくる最初の2プロセス)。
kworker はカーネルが起動するスレッドのプレースホルダープロセスであり、これは実際にカーネルプロセスのほとんどを実行しているものである。割り込みやタイマー、I/Oなどの特定のケースで使われる。これらは典型的にプロセスを実行するシステムタイムの大部分を占めている。
これをシステムから安全に排除する方法はなく、KDEとは無関係である(プログラムがカーネルに要求するいくつかのシステムコールを除く)。


1. カーネルをディストリが配布する最新のものにアップデートする。
2. unameコマンドでカーネルのバージョンが2.36以上であることを確認する。バージョン2.36以降が重要で、このバージョン以降がカーネルのDRM_KMS_POLLINGを無効化できるためである。2.5カーネルではDRM_KMS_POLLINGを無効化できない。たぶん2.35のバグフィックスでパッチが当たったのかもしれない。
3. 新しいカーネルで再起動し以下のコマンドを実行する。 
sudo echo N>/sys/module/drm_kms_helper/parameters/poll 
これは強制的にシステムの負荷を軽減し通常の状態に戻す。このコマンドが有効なのはシステムが再起動されるまでである。再起動後に値はpoll=Yに戻ってしまう。この効果を維持したい場合は以下のコマンドを実行する。
echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf
追記:カーネル3.8xから3.9-rc5では、i915チップでIRQの衝突が起こるかもしれない。またdrm pollパラメータは何らかの理由で無効にされる。この解決方法はもう使えないかもしれない。スキルがあるなら以下の内容を試してほしい:
1. カーネルを3.2x系にダウングレードする
2. /etc/rc.localに「echo N> /sys/module/drm_kms_helper/parameters/poll」を追記するか、「drm_kms_helper.poll=0」をgrubの起動パラメータに追加する。
これは単なる応急処置なので続けて解決策を探ってほしい。

最初のスレに /sys/firmware/acpi/interrupts/ の値が高いものをdisableしろと書いてあるのだがいずれも値はゼロのままで、ここには割込みらしきものが出ていない。

2つ目のスレの解決策は古いし3.8付近では無効らしいので理屈がわかっている場合のみ適用したほうがいい。
なかにはUSBモジュールがボトルネックだとか、カーネルがやっていることだからお前が心配することじゃないよみたいな殿様カキコがあったりするのだが、いくつかはdrm_kmsに言及している。

DRM(Direct Rendering Manager)はXアプリがサーバを介せずに直接アクセスする手段を提供するもので、特定のビデオチップのためのカーネルモジュールらしい。KMS(Kernel Module Settings)とはカーネルからモニタの解像度や色数を設定するもの。

うちの構成はNVIDIAプロプライエタリドライバなのでKMSは使われてないはずなのだがどこかで衝突してる可能性はある。


とりあえずカーネルとドライバをアップデートして、 grub2の起動オプションに に drm_kms_helper.poll=0 を追加して様子を見る。これが有効になったかどうかはdmesgには出てこない。

20140115: topの観察を続けていたらディスクアクセスが起こっている最中にupdatedb.mlocateが起動されている。簡単に言うとファイルのインデックスを作っているだけなのだが、cronで1日1回明け方にまわしているだけだと思っていたのだがな。なんらかの拍子に起動されることがあるのかと思ったのだがそういう説明はないっぽい。

20140117:DRM_KMSのpollを0にしてupdatedbを止めてから症状が出なくなったが原因が特定できない。ただのswapだった可能性もあるが今のカーネルは空きメモリをキャッシュに使うのでメモリの使用量からではスワップアウトかどうかが追えないのでなんともいえない。もしかすると最初に見たkworker群と後に見たupdatedbは関係ないのかもしれん。