Windowsの割り込み負荷を計測する

krvir

タスクマネージャでどのプログラムも大してCPUを使っていないのに、なぜかCPU利用率が高い。こういう経験はありませんか?それはカーネルの割り込み処理が悪さをしているのかもしれません。

今回は、その調査方法から解決までの道のりを書いてみたいと思います。

基礎知識:ユーザーモードとカーネルモード

WindowsマシンのCPUはユーザー モードとカーネル モードという2つをスイッチしてプログラムの実行を行っている。

ユーザー モードとカーネル モード

詳細を話すことは本稿の目的でないので簡潔に説明する。ユーザーモードでは、普通のアプリケーションが実行される。カーネルモードでは、ドライバやアンチウィルスソフトやファイヤウォールといった、少し特殊なソフトウェアが動作する。

ユーザーモードで実行されるプログラムの、アプリケーション毎の負荷はタスクマネージャで簡単に確認できる。が、カーネルモードで動くプログラムの実行負荷を計測するのは難しい。

タスクマネージャから、パフォーマンスタブを開き、「表示」メニューから「カーネル時間の表示」を選ぶと、カーネルモードでCPUが処理した総時間がグラフ表示される。

krvir

赤線で表示されるのが、それである。これによって、負荷の原因がユーザーモードで動作するプログラムなのか、カーネルモードで動作するプログラムなのかの切り分けは可能であるが、カーネルモードであった場合、ではどのプログラムが悪さをしているのかまでは分からない。

32bit Windowsでカーネルモードプロセスの詳細を調べる

32bit Windows(XP, Vista, 7)の場合は、Kernrate Viewerというプログラムを使うと、1秒間あたりに何回の割り込みが発生しているか(≒何回カーネルモードでの処理要求が合ったか)を調べることが出来る。

実際のログは以下の様な感じで採取できる。

Results for Kernel Mode:
-----------------------------

OutputResults: KernelModuleCount = 191
Percentage in the following table is based on the Total Hits for the Kernel

Time   227323 hits, 25000 events per hit --------
 Module                                Hits   msec  %Total  Events/Sec
ntkrnlpa                             199259     146979    87 %    33892426
VSApiNt                               25986     146979    11 %     4420019
win32k                                  593     146979     0 %      100864
halmacpi                                373     146979     0 %       63444

これで負荷の高いモジュールが何か調べることができる。ntkrnlpaはWindowsに動作されるメモリ管理か何かのモジュールで、おそらくページフォルトが発生した場合の割り込みを出しているのだと思う。これが高いのは問題ない。上記のログでの問題は、VSApiNtというモジュールだ。この名前でファイル検索をすると、VSApiNt.sysというファイルがTrendMicroのフォルダでヒットする。つまり、アンチウィルスソフトが原因であった、と分かる。以下の記事も参照。

EclipseやSQL Developerが立ち上がるのがすごく遅い

Vista以降のOSでカーネルモードプロセスの詳細を調べる

Kernrate Viewerは優れたツールであるが、32bit Windowsでしか動作しない。それも、公式にサポートしているのはWindows XPまでだ。Windows7 32bitでも動作したものの、サポートされているわけではない。

じゃあどうすればいいんじゃー、とずっと悩んでいたのだが、こないだ別の方法を見つけたのでここに記す。以下のページを参照した。

Troubleshooting High CPU Utilization issues using Tracelog.exe

このツールを使うためにはWindows Driver Kit (WDK)というのをインストールしなければならない。Microsoftのページからダウンロードできるが、数百MBあり、結構ダウンロードが面倒ではあるが、それ以外に方法がないので我慢しよう。今回は、Windows 7 64bit、WDK 8.1という組み合わせで検証した。

WDKをインストールすると、インストールディレクトリのtoolフォルダの下に、tracelog.exeというアプリが入る。これを使うと、Deferred procedure calls (DPCs) と Interrupt service routines (ISRs)が測定できる。どちらの数値も大きいほど負荷が高いと思って間違いないと思うが、詳しく調べると以下のような定義であった。

DPCs
プライオリティの低い割り込み処理を再スケジュールして後回しにする要求が発せられた回数。マルチコアCPUでこれが別のコアでスケジュールされるとオーバーヘッドが大きくなるらしい。この動作はWindowsに特有のもので、レジストリをいじってOFFにできる。

参考:
Sun ONE Directory Server インストールおよびチューニングガイド 第 5 章 オペレーティングシステムのチューニング

ISRs

割り込みハンドラが呼び出したルーチンの個数。おそらく、のべ個数。

・・・という感じ。使い方はいたって単純で、

tracelog -start -f test.etl -dpcisr -UsePerfCounter -b 64
tracelog -stop
tracerpt test.etl -report dpcisr.html -f html

上記を順に実行するだけ。ただし、1番目のコマンドを入力してから2番めのコマンドを入力するまでの間は、30~60秒くらい開けること。(この間にDPC/ISRを計測する)

tracerptというコマンドは、system32フォルダの中に実体があり、すでにパスが通っていた。

最終的に出来上がったdpcisr.htmlを開くと、モジュールごとのDPC/ISR値が表示されるので、負荷の大きいモジュールを特定できる。

負荷の大きいモジュールを見つけたら

上記の方法で負荷の高いモジュール名を見つけたら、そのモジュールが何なのか調べよう。

  • パス、モジュール名からアプリ(ドライバ)を特定する
  • ネットで検索してみる
  • ファイルのプロパティを見てみる

大体上記のような方法で特定できるはずだ。最も、ここまでの手順を実行できる程度のスキルがあれば、言わなくても分かることかもしれないが。

原因を特定できたら、基本的にはそのプログラム/ドライバをアンインストールするしか無い。最新版を使ってみるとか、他製品に乗り換えるとか、そのくらいしかできることはない。

あと、マルチコア環境の場合で、DPCが高い場合は、

HKEY_LOCAL_MACHINE¥System¥CurrentControlSet¥Services¥NDIS¥Parameters

にある、ProcessorAffinityMask の値を0にすると改善されたという報告がいくつかあった。これも試してみるといいかもしれない。

3件のコメント

  1. しまねこ より:

    こんにちは
    Shuttle DS81 (Intel H81) に Core i7-4790S(4コア/8スレッド)、Win7 SP1 64bit でセットアップ直後、
    タスクマネージャーのパッフォーマンスタブで、CPU使用率8のうち1つだけが常時40%~を示していて、悪戦苦闘しておりました。
    ProcessExplorerでは、SystemIdleProcess 99%、このサイトに辿り着き、
    ご指南通り tracelog.exe の手順で原因特定出来ました。
    ISRの"usbport.sys"が原因と判明、ドライバを手動であてなおし(Intel 8Series/C220 Series USB EHCI)、解決しました。
    有用な記事に助かりました。ありがとうございました。

  2. しまねこ より:

    こんにちは
    追記
    その後、リブートを試みた際、BSoD発生。
    再起動後、カーネル負荷の現象は元に戻っていました。
    最終的に、該当ドライバの無効化で解決しました。
    DS81のUSBポート(全面2.0x8、背面2.0x2、3.0x2)すべて使えるので、問題なしでした。(ボード上にUSBコネクタあり)
    重ねてありがとうございました。

  3. withpop より:

    コメントありがとうございます。
    お役に立ったのであれば幸いです。

    私の場合は、同じようにAMDのドライバ(チップセットドライバ)により、常に30%程度CPUを消費している状態でした。私の場合は、ブラウジングや動画再生がメインになるようなPCで現象が発生しましたので、最終的にLinuxを入れて使うことにしました。

    WindowsとLinuxをデスクトップ用途で長年併用していますが、最近だとWindowsの方がトラブルに見舞われる機会が多い気がします。
    特にドライバまわりだとどうにもできない場合が多いので何とかして欲しいです。

ただいまコメントは受け付けていません。