技術は記憶の彼方へと

覚えたつもりですぐに忘れるエンジニアの備忘録

【備忘録】パフォーマンスモニターを使ってCPU状況を把握する

前回の記事が2022-06-11って事なので、一年ほど空きました...
何というか、転職したり配属変わったりとバタバタしてまして、前回記事にしたHackerRankもそんなに触れてない状況です。
さて、今回は配属された先がWindows系の組み込み機器のようなものを作ってるようでして、今までLinuxで生きてきた人間にとってはちょっと新鮮な感じがしています。
その中でCPUスパイクやメモリリークといった事象が発生していないかを見ることが多くなったので、Windows標準で入っているパフォーマンスモニターを使うことが多くなってきたので、備忘録に残そうと思います。
どういうカウンタの値見てるかとかに絞って情報を記載しておこうと思います。メモリは次回にでも出来たらいいなぁ。

2023-09-23 追記
メモリに関しての記事をようやく書きました。
cloudvelse.hatenablog.jp
Win系システムってことで、バッチファイル(Batファイル)君も扱うことになってるわけですが、あれは....なんなんだ。人がやるものなのか?
もし、精神的に余力があるなら....記事に....したくないなぁ。どうせ職場の環境とうちの環境違うから動かないんでしょ?知ってるからな。
前置きはこの辺で、本題行きましょうか。

目次


パフォーマンスモニター


Windowsに標準で入っている、OSのパフォーマンスの推移を総合的に確認することができるツールでありあまり負荷をかけることなくパフォーマンスログを取得することができるツールである。
システムの状況をタスクマネージャ等で常時監視せずに、ファイルに出力させるなどして確認に使うことができる便利なツールとでも思えばいいかもしれません。
基本的にログは.blg拡張子のバイナリ形式で保存されますが、設定でCSV等に変更することは可能ですがログ取得開始時に起動しているプロセス以外で後から起動したプロセスについては記録できなくなってしまう仕様となっている為、バイナリ形式で取得してからrelogコマンドで変換して解析することをお勧めします。
パフォーマンスモニターのツール上でどのカウントを取得するか、採取周期はどうするかといったことを設定してデータコレクタセットを作成することもできますが、一つずつ追加して...としていくのが私は大変だと思いましたので、コマンドと取得したいカウンタをリストにしたTEXTファイルを用いる方法をお勧めします。
方法については、下記Microsoft社のサポートブログが参考になると思います。

パフォーマンス ログ収集 | Microsoft Japan Windows Technology Support Blog

CPU(プロセッサ)全体に関するカウンタ


今回の本題です。CPU利用率やスパイク調査等で私が主に使用しているカウンタについてを見ていきます。

\Processor Information\ % Processor Utility

システム全体のCPU利用率を表します。他の技術ブログなどでは、\Processor(_Total) % Processor Timeが紹介されていることが多いです。
どちらも同じような値を示すものではありますが、Processoe Informationはシステムの高性能・高機能化に対応するためWindows Server 2008 R2 から追加されたパフォーマンスカウンターであり、それ以降のシステムであればこちらを活用することをMicrosoft社として推奨しているようです。
というのも、Processorカウンタは64コア以上のCPUや、NUMA(Non-Uniform Memory Access)に非対応だったりするようです。
クロック周波数が使用状況によって変化するCPUに対応しており、タスクマネージャ上で表示されているCPUの「使用率」と参照している値が同じになります。
パフォーマンスカウンターがベースのクロック周波数を基準に作成されるため、負荷状況によってクロック周波数が変化するCPU搭載の場合は100%を超える値が表示される可能性があります。
※なおタスクマネージャでは、100%を超えた場合は切り捨てて100%で表示する仕様のようです。

常に閾値を超えるような場合にはCPUボトルネックが疑われます。
この値は、アプリケーション処理のためにCPUが使用されたことを意味していて高い値でありかつパフォーマンスに問題がある場合にはCPUアップグレードや負荷分散、又は不要なサービスの停止を検討する必要があると考えられるでしょう。
ただ、後述するランキューの値が低くOS的にパフォーマンスに問題がない場合もあります。

\Processor Information\ % Processor Time

CPUがIdle以外のスレッドを処理のするために使用された経過時間の割合を表します。
このカウンタはクロック周波数について意識していない為必ずしも上記のProcessor Utilityと一致するわけではない点に注意が必要です。
例えば、単位時間を10秒と雑に決めた場合に2秒間CPUが利用されれば20%と表示する。といった動作をするカウンタとなります。この例は雑に基準単位時間を決めましたが本来はもっと詳細な時間で決められています。
あくまでどれくらい使用されていたのか、どれくらいの割合でプロセスに利用されていたのかを参考程度に知るための指標となります。

\System\Processor Queue Length

CPUの処理を待つスレッド数、ランキューを表しています。あくまで処理待ち数であり実行中のスレッドは含まれません。
あくまでカウンタ採取時の瞬時値が表示されるわけですが、上昇傾向や常に高く維持されているような場合はCPU負荷が大きくなっている状態が疑われます。
マルチコア/マルチスレッドなシステムの場合は閾値も比例的に高くなりますが、CPUを占有する遅い処理やアクセス過多によりCPUボトルネックとなっている状態を疑い、ミドルウェアやアプリケーションにおける調査を検討する必要があると考えられます。

ただ、本指標は瞬間瞬間だけを見て判断ができる指標ではありません。
待ち行列というものは、リトルの性質と呼ばれる重要な性質があります。
それは、長期間観測した待ち行列の長さの平均が、システム負荷量の処理の積として得られるというものであり、以下の等式で説明されます。
<平均系内客数> = <平均到着数> × <平均サービス時間>
ここで言うところの、<平均系内客数>は平均の待ち行列長、<平均到着率>は単位時間当たりの処理要求数の平均(いわゆるシステム処理負荷量)、<平均サービス時間>は1つの処理を行うのにかかった時間平均(処理遅延)に相当するものとして計算をすることによってシステムの負荷状況や処理遅延の状況を知ることができるということがわかると思います。

上記から、この指標を判断するには瞬時的な上下なのか長期的な状態であるのかから判断をしていくことになる。
急上昇後にすぐに降下する。いわゆるグラフ等で見た際にスパイク状となっている場合については、実行待ちとなるスレッドは短時間で解消されており問題となる状態ではないと判断ができます。
逆に、常時高い傾向がみられる場合や上昇し続けるような傾向にある場合には、各アプリケーションやミドルウェアの調査を実施したほうが良い状態であると判断ができます。

つまるところ、パフォーマンスの体感ともいえる部分は最終的に処理遅延で決まってくる。処理待ち行列が多いこと自体が問題ではない。ということになりますので、注意が必要です。

\Processor\Interrupts/Sec

プロセッサが処理した1秒当たりのH/W割り込みの回数を表します。
割り込みが発生するとそれまでに実行されていたプロセスを一時停止させて処理を行うことになる為、頻発するとプロセッサにおける処理効率に影響を及ぼすことになってしまいます。
もし頻繁に発生するようなことがあった場合には、最近追加されたデバイスドライバ等を無効化や削除して変化があるのかを確認してみることをお勧めします。
変化があった場合には、そのデバイスドライバを通じて行われる割り込みがCPUをボトルネックにさせている原因であると考えることができるため処理について調査し改善を検討することができるでしょう。

プロセス毎のCPU使用状況


これまで記述してきた、プロセッサ全体での使用状況からCPUにボトルネックの傾向がみられることやスパイクがみられる場合にどのプロセスが影響をしているのかを知る為の指標となります。
ただ、これらのカウンター値は上限がCPUコア数×100となっておりCPUコア数によっては100%を超える値を取る可能性があります。例として16コアCPUの場合、0~1600の範囲での値となります。

\Process(プロセス名)\ % Processor Time

プロセスのスレッドが命令を実行するためにプロセッサを消費する経過時間の割合を表しています。
Processor TimeカウンタはProcessorオブジェクト、Processor Informationオブジェクトにもあるが、こちらはインスタンスとして指定したプロセス単体での使用率を表示するものであるため、大量に消費しているプロセスの特定に役立つカウンタとなります。

\Process(プロセス名)\ % Privileged Time

プロセスがカーネルモード(特権モード)で実行するためにプロセッサを消費する時間の割合を表します。
主に、カーネルモードで動くプロセスはOSの基本動作を担当するものであることがほとんどであり、起動するサービスを停止させる等対策ができないわけではないができる対策に限りがあることや、不用意にサービス停止をするとOS自体の起動・動作に影響を及ぼしかねないことに注意が必要となります。

\Process(プロセス名)\ % User Time

プロセスがユーザモードで実行するためにプロセッサを消費する時間の割合を表します。
おもに、アプリケーション動作を担当するものとなる為ユーザモードの処理がプロセッサを圧迫している場合は起動するアプリケーションを減らすことや該当するプロセスの処理内容を見直し最適化する等の対策を考えることができます。

最後に


今回は、PerfmonにおけるCPUに関連する項目についてを見ていきました。
実際にこれらを解析してスパイクしているプロセスを調査したり対策を講じたりということを行っている身として、どのカウンタを見ればいいのか等非常に多く探すのも大変になりますね。
Linuxで似たようなことをやろうと思うと、syslogを見たりvmstat、top、sarあたりを確認していけば同じような解析ができると思います。
sarだと、Ubuntuとかで正しく表示できない...なんてことがあったような気もします。テキストにしてしまえば問題はなかったかと思いますがディストリビューションで差分があるなんてあるあるですね。
Windowsだとこれらである程度は見れますが、これだけでは情報が足らないなんてこともよくあります。
そんな時は、WPRを使ってみたりProcess Exploreを使ったりとMicrosoft社が出してる解析ツールをあれこれ駆使して詳細まで追いかけ続ける必要が出てきてしまうので大変ですね。
最近は、バッチファイルに苦しめられている為備忘録を作っておきたい思いはあるのですが、何が悪いのかわからなかったりネット上での参考ソースをそのままコピーしても動かないってことが多発するせいで役に立たなさそうなんですよね....
何というか、狂気的な雰囲気を感じています。
Linuxシステムに帰りたい...そう願う日々です。
それでは、今回はこの辺で。