WPR/WPA実践 ── 「PC全体が重い」をシステム全体から調べる性能調査入門

· 更新日: · · Windows, パフォーマンス, WPR, WPA, ETW, 性能調査, 障害調査, Windows開発

更新履歴(5件・最終更新 2026年09月06日)

この記事に加えた変更の記録です。アーカイブした更新前のバージョンは、DOI付きの固定URLから読めます。

技術的な主張と条件はそのままに、採取からCPU・待ち時間・I/Oの切り分けへ進む流れを冒頭で示し、WPAの操作、シンボル設定、待ち解析、ETLの取り扱いを小見出しと目的別リンクで追いやすく整理した。
知識マップの関係を総点検し、説明文と食い違っていた関係(向きの逆転・過剰な一般化・述語の取り違え)を修正しました。本文の説明は変えていません。
知識マップの関係を総点検し、説明文と食い違っていた関係(向きの逆転・過剰な一般化・述語の取り違え)を修正しました。本文の説明は変えていません。
知識マップの関係を総点検し、説明文と食い違っていた関係(向きの逆転・過剰な一般化・述語の取り違え)を修正しました。本文の説明は変えていません。
知識マップの「ETWロギングモードはWPAに推奨されない」という関係を、「長時間のトレース採取はWPAでの解析に向かない」に改めました。ロギングモード自体はWPAの通常の入力のためです。本文の説明は変えていません。
初版公開
この記事を引用する(DOI: 10.5281/zenodo.22054273)

この記事はZenodoにアーカイブされています。常に最新版へ解決されるDOIと、いま表示している版に固定されたDOIの両方を下に示します。

小村 豪(2026)「WPR/WPA実践 ── 「PC全体が重い」をシステム全体から調べる性能調査入門」合同会社小村ソフト. https://doi.org/10.5281/zenodo.22054273 https://comcomponent.com/blog/wpr-wpa-system-performance-analysis/

DOI(最新版)
10.5281/zenodo.22054273
DOI(この版)
10.5281/zenodo.22452245

「アプリを入れたらPC全体が重くなった。しかし、タスクマネージャーではCPUにもメモリにも余裕がある」「1台だけ起動に3分かかる」──こうした相談で困るのは、どのプロセスを調べればよいかさえ分からないことです。

アプリAが遅くても、原因はウイルス対策ソフトのスキャン、別サービスの大量書き込み、複数プロセスにまたがるロックの連鎖かもしれません。必要なのは、OS全体の動きを1本の時間軸で記録し、どこで時間が消えたかを追うことです。

そのための道具が、Windows Performance Recorder(WPR)とWindows Performance Analyzer(WPA)です。WPRはETW(Event Tracing for Windows)を使って記録を採り、WPAはその記録をグラフとテーブルで読みます。CPUを使ったプロセスとスタック、スレッドが待っていた相手、ディスクI/Oの発行元とファイルを、時刻に沿って調べます。

この記事で答えるのは、「PC全体の遅さをどう記録し、CPU・待ち時間・I/Oのどこを調べるか」です。中小企業の情シス担当者とWindowsアプリ開発者に向け、2026年8月時点の一次情報にもとづいて、採取の実務から解析までを説明します。特に「CPUが高い場合」と「CPUが低いのに遅い場合」の違いを軸に読み進めてください。

ファイルやレジストリへのアクセスを調べるProcess Monitor、.NETアプリのCPUやGCを追うPerfViewとの使い分けは、2章で整理します。

1. まず結論

基本の流れは「WPRで採取 → WPAで問題の時間帯に絞る → CPU・待ち・I/Oを切り分ける」です。 特定のプロセスだけでは分からない問題も、全プロセスとカーネルを同じ時間軸で追うことで調べられます。12

採る場所と、読む場所を分ける

採取用のwpr.exeはWindows 8.1以降のOSに標準搭載されており、追加インストールは不要です。GUI版のWPRUIと解析用のWPAはWindows ADKに含まれます。「顧客環境ではwpr.exeで採るだけ、読むのは手元のWPA」という分担ができるため、ソフトを追加できないサーバーでも採取できます。12

再現できる事象なら、管理者権限でwpr -start GeneralProfile -filemode → 事象を再現 → wpr -stop C:\temp\trace.etlが基本の3手順です。3 保存先フォルダーの準備、採取の承認、ETLの取り扱いを決めてから実行します。 待ち受ける場合や起動中の問題には別の採り方があるので、3章と8章を確認してください。

WPAで最初に開くグラフ

まず事象の区間に絞り、次の表で調べる方向を選びます。45

その区間の状態 最初に見るもの 確かめること
CPUが高い 5章: CPU Usage (Sampled) どのプロセス・スタック・関数がCPUを使ったか
CPU全体は低いが、1コア・1スレッドが張り付いている 5章: CPU Usage (Sampled) 全体の使用率に埋もれたCPUボトルネックがないか
CPUにも特定コアにも張り付きがないのに遅い 6章: CPU Usage (Precise) どこで待ち、どれだけ待ち、誰が待ちを解いたか
ディスクやファイルアクセスが疑わしい 7章: Disk Usage / File I/O 待ち行列と装置の処理時間、I/Oの発行元とファイル

Sampledは約1ミリ秒ごとのサンプリングでCPU時間の内訳を見るものです。6 Preciseはコンテキストスイッチの完全な記録から待ちを追います。Waits → ReadyingProcess → ReadyThreadStackを手掛かりに、待ちを解いた相手を辿ることが、この記事で最も伝えたい技術です。47

目的に合わせた読み方

採取を担当する方は2章と3章から、採取済みのETLを読む方は4章から進めます。スタックを関数名で読むにはシンボル設定が必要で、自社アプリにはPDBのパスを追加します。8 .NETのJITコードを調べる場合は、採取時のCLRイベントも必要なので、4章の.NET向けの説明を採取前に確認してください。

調査全体の進め方とETLの取り扱いは9章にまとめます。ETLにはプロセス名・ファイルパスなどの内部情報が含まれるため、必要最小限の採取とし、社外に渡す条件を先に決めます。

図の実線は常に成り立つ関係、破線は条件付きの関係です(成立条件は詳細ページの各関係の説明に記載)。関係すべての一覧(全16件、根拠・確度つき)と主要概念の定義は知識マップ詳細ページにまとめています。データ: JSON-LD / Turtle

2. 道具の位置づけ ── 採るのがWPR、読むのがWPA

Windows Performance Toolkit(WPT)は、Windows ADK(Windows Assessment and Deployment Kit)に含まれるパフォーマンス調査ツール群で、中心はWPRとWPAの2つです。2 役割は明確に分かれています。

WPRは採取、WPAは解析

  • WPR(Windows Performance Recorder) = 採取。ETWのプロバイダー群を「プロファイル」という単位で束ねて記録を開始・停止し、ETLファイルを作ります。コマンドライン版のwpr.exeはWindows 8.1以降のOSに標準搭載で、追加インストール不要です。GUI版(WPRUI.exe)はADKに含まれます。1
  • WPA(Windows Performance Analyzer) = 解析。ETLファイルを開き、グラフとテーブルで分析します。ADKのインストールが必要です。2

つまり、コマンドラインで採取するだけなら、顧客環境に追加のソフトを入れる必要はありません。OS標準のwpr.exeで採り、ETLファイルを持ち帰り、手元のPCのWPAで読む──パケットキャプチャで「pktmonで採ってWiresharkで読む」のと同じ分担が成立します。

WPRで採りWPAで読む分担顧客環境ではOS標準のwpr.exeで記録してETLファイルを作り、持ち帰って手元のPCにADKで入れたWPAで解析する手元のPC(ADKでWPA導入済み)顧客環境(追加インストール不要)持ち帰るWPAでグラフ・テーブル解析ETLファイルwpr -start → 事象を再現 → wpr -stop

Procmon・PerfViewとの使い分け

似た道具との使い分けも先に整理しておきます。

  Process Monitor PerfView WPR + WPA
答えてくれる質問 どのプロセスが、どのパスに、何をして、どうなったか .NETアプリのCPU・GC・アロケーションはどうなっているか OS全体で、どこで時間が消えたか
守備範囲 ファイル・レジストリ・プロセス起動の操作ログ マネージドコード中心 CPU・待ち・ディスク・ファイルI/O・電源などシステム全体
向く症状 設定が読まれない、ACCESS DENIED 自社.NETアプリ単体の遅さ・メモリ PC全体が重い、CPUが暇なのに遅い、犯人プロセス不明
記事 Procmon実践ガイド PerfView実務入門 この記事

Procmonが「何をしたか」の操作ログ、PerfViewが「.NETの中で何が起きたか」だとすれば、WPAは「どこで時間が消えたか」を全プロセス横断で会計監査する道具です。

自社アプリのイベントを一緒に記録したいとき

ETWそのものの仕組みと自社アプリをETWに計装する方法は「Windowsイベントログ・ETW入門」で扱っています。自社アプリがETWイベントを出していれば、トレースに自社アプリの節目も一緒に記録でき、突き合わせが一気に楽になります。

ただしWPRは、選んだ記録プロファイルで有効化されたプロバイダーのイベントしか記録しません。GeneralProfileに自社プロバイダーは含まれません。一緒に記録する場合は、自社プロバイダーを有効化するカスタム記録プロファイル(.wprp)を用意し、wpr -start GeneralProfile -start MyApp.wprp!MyAppProfileのように、.wprpファイル内のプロファイル名を!で指定して併用します3。

3. 採取の実務(WPR) ── start、再現、stop

実行前に決めておくこと

本番環境では、短時間の採取でも無条件に安全とは考えないでください。 ETWは軽量ですが、スタック付きのイベントを大量に記録するとCPUとメモリを一定量消費します。業務への影響が少ない時間帯を選び、通常の変更作業と同じ承認プロセスに乗せます。

再現できる場合は、直前に開始し、直後に停止して数分以内に収めます。保存先フォルダーを用意し、ETLを渡す相手・保管期限・削除方法も先に決めます。内容に関する注意は9章にあります。

以下は、その場で再現できる事象をFileモードで採る例です。 いつ起きるか分からない事象は3.1節のMemoryモード、起動・ログオン中の問題は8章へ進んでください。

通常の採取は「start → 再現 → stop」

管理者として開いたコマンドプロンプトで実行します。-profilesは事前の一覧確認、-statusは採取中の状態確認です。末尾の-cancelは途中で中止して破棄するときだけ使い、通常の保存手順には含めません。

:: 使える組み込みプロファイルの一覧
wpr -profiles

:: 1. 採取開始(汎用プロファイル、ファイルモード)
wpr -start GeneralProfile -filemode

:: 2. 事象を再現させる(採取中の状態確認は wpr -status)

:: 3. 停止して保存(問題の説明を添えられる)。
::    保存先フォルダーは事前に作っておく(無いと -stop が保存に失敗する)
mkdir C:\temp 2>nul
wpr -stop C:\temp\slow-pc.etl "アプリX起動中にPC全体が重くなる事象を再現"

:: 途中でやめる場合は保存せず破棄
wpr -cancel

何を記録するかはプロファイルで選ぶ

-startに指定するのがプロファイルで、その調査に必要なETWプロバイダーの束です。3 よく使うものだけ覚えれば足ります。9

プロファイル 記録する内容 使いどころ
GeneralProfile CPUサンプル・コンテキストスイッチ・ディスクI/Oなど汎用一式 まずこれ。何が悪いか分からない段階の第一手
CPU CPU使用の詳細 CPUが焼けていると分かっている場合
DiskIO ディスクI/O活動 ディスクが疑わしい場合
FileIO ファイルI/O活動 どのファイルへのアクセスかまで追う場合

プロファイルは-startを並べて複数同時に指定できます(例: wpr -start GeneralProfile -start FileIO -filemode)。3

WPR採取の流れとモードの選び方手元で再現できる事象はファイルモードで短時間・確実に採り、いつ起きるか分からない事象は既定のメモリモードのリングバッファで待ち受ける。起動やログオン中の事象はブートトレースを使う。いずれも開始・再現・停止の手順は同じ手元で再現できるいつ起きるか分からない起動・ログオン中事象はいつ起きるか-filemodeで短時間・確実に採取メモリモード(既定・リングバッファ)で待ち受け(3.1節)ブートトレース(8章)wpr -start → 事象を再現・発生 → wpr -stop

3.1. MemoryモードとFileモード ── 再現できるか、待ち受けるか

WPRの記録先には2モードあり、既定はMemoryモード(メモリ上の循環バッファ)です。

Memoryモードは、発生を待ち受けるときに使います。 古いイベントから上書きされるリングバッファなので、いつ起きるか分からない事象を採りっぱなしで待ち受け、起きたら止める使い方に向きます。

Fileモードは、短時間で確実に再現できるときに使います。 -filemodeを付けるとFileモードになり、連続したファイルにすべて記録されます。こちらは上書きで消えない代わりに、上限はディスクの空き容量だけで、ファイルは際限なく育ちます。10

MemoryモードとFileモードの記録のされ方Memoryモードはメモリ上の循環バッファに記録し、古いイベントから上書きされて直近だけが残るため待ち受け向き。Fileモードはファイルに全部残るが上限はディスク空き容量だけで、短時間の確実な再現向きETWイベントの流れMemoryモード: 循環バッファ(古い順に上書き → 直近だけ残る)Fileモード: ファイルに全部残る(上限はディスク空き容量)いつ起きるか分からない事象の待ち受け向き短時間で確実に再現できる事象向き

使い分けの目安は次のとおりです。

  • その場で再現できる → Fileモード。再現の直前に開始、直後に停止し、採取は数分以内に収める
  • いつ起きるか分からない → Memoryモード(既定)で待ち受け。発生したらすぐwpr -stop
  • 数分のGeneralProfileでもETLは数百MB〜GB級になり得ます。大きすぎるファイルはWPAで解析できないことがあるため、「長く採るほど良い」は逆効果です1011

GUIで採取する場合

GUIで採る場合はWPRUIを起動し、プロファイルとLogging modeを選んでStart/Saveするだけです。手順の詳細は公式のHow-toにまとまっています。11 顧客先の担当者に採取を依頼する場合も、開始・再現・停止の手順を中心に、前提条件と中止時の操作を分けて手順書にできます。

4. WPAの読み方の基本 ── グラフ、テーブルの黄金律、時間の絞り込み

採れたETLをWPAで開くと、左側のGraph Explorerに、System Activity・Computation・Storage・Memoryなどのカテゴリでグラフのサムネイルが並びます。12 見たいグラフを右のAnalysisタブへドラッグすると、上にグラフ、下にテーブルが表示されます。

押さえるのは、列の並べ方・時間の絞り込み・シンボル設定の3つです。グラフごとに操作を覚え直すのではなく、この共通の読み方から始めます。

4.1. 列の並びが、集計の切り口を決める

WPAのテーブルには金色と青色の2本の縦バーがあり、金色バーより左の列の順にデータが階層化(グルーピング)され、青色バーより右の列が集計値になります。13

「Process → Stack」の順に並べればプロセスごとのスタック集計、「Stack → Process」の順なら同じスタックを使う全プロセスの集計、と列をドラッグして並べ替えること自体が分析操作です。この一点を理解すると、WPAのすべてのテーブルが同じ読み方になります。

テーブルの黄金律 ── 2本のバーと列の役割金色バーより左の列の並び順でデータが階層化され、金色と青色のバーの間が表示列、青色バーより右が集計値になる。列をドラッグして並べ替えること自体が分析操作になる金色バーより左: グルーピング列(並び順 = 階層)金色バーバーの間: 表示列青色バー青色バーより右: 集計値(Sum・%など)列のドラッグ = 分析操作(Process→Stackならプロセス別のスタック集計)

4.2. 事象が起きた時間帯だけに絞る

グラフ上でドラッグして範囲選択し、右クリックから「Zoom」で、その区間だけの集計に切り替わります。性能調査は常に「事象が起きていた区間」だけを見るのが原則です(9章)。

4.3. シンボルを読み込み、スタックを関数名で見る

スタックを関数名で読むには、メニューのTrace > Load Symbolsを実行します。14 既定でMicrosoftの公開シンボルサーバー(msdl.microsoft.com)を参照するため、Windows本体のスタックはインターネット接続があれば解決できます。

自社アプリの関数名まで見るには、Trace > Configure Symbol Pathsで自社アプリのPDBのフォルダーを追加します。8 PDBが何者で、なぜリリースビルドでも必ず保存しておくべきかは「PDB(プログラムデータベース)とは何か」にまとめました。

.NETはNGenイメージとJITコードを分けて考える

.NET FrameworkのNGenネイティブイメージについては、WPRが採取時にNGen用PDB(.ngenpdb)を生成してトレースの隣のフォルダーに置き、WPAが自動で参照します。8 これはNGenイメージ専用の仕組みで、JITで動く通常の.NETアプリの自作コードは対象外です。

JITコードのアドレスと関数名の対応はCLRが出すJITイベントから解決されるため、.NETアプリを調べるときは、CLRのプロバイダー(Microsoft-Windows-DotNETRuntimeと同Rundown)を有効化する記録プロファイル(.wprp)を用意し、2章の自社プロバイダーと同じ要領で wpr -start GeneralProfile -start MyDotNet.wprp!プロファイル名 の形で併用して、CLRのイベントをトレースに含めておきます(手元のWPRが使える組み込みプロファイルは wpr -profiles で確認できます)。

そのうえで、ソース行との対応づけのためにビルドで生成されるPDBを保存し、上記のシンボルパスに追加してください。

スタックを関数名で読むためのシンボル解決Trace Load Symbolsを実行すると、Windows本体はMicrosoftの公開シンボルサーバーから、自社アプリはシンボルパスに追加したビルドPDBから解決される。NGenイメージはWPRが生成するNGen用PDB、JITの.NETコードはトレース内のCLR JITイベントとビルドPDBが解決の元になるTrace > Load SymbolsWindows本体: 公開シンボルサーバー(msdl)自社アプリ: Configure Symbol Pathsに追加したビルドPDB.NET FrameworkのNGenイメージ: WPR生成の.ngenpdbJITの.NETコード: トレース内のCLR JITイベント + ビルドPDB

4.4. CPU・待ち・I/Oのどれを調べるか決める

準備ができたら、事象の区間でCPUが高かったか、低かったかを見ます。高ければ5章のSampledへ。低い場合も、まず特定のコア・スレッドの張り付きを確認し、それもなければ6章のPreciseで待ちを追います。ディスクが疑わしければ7章へ進みます。

症状からWPAのグラフを選ぶ分岐事象の区間にズームし、CPUが高ければCPU Usage Sampledへ、低いのに遅ければコアの張り付きを確認したうえでCPU Usage Preciseの待ち解析へ、ディスクが疑わしければDisk UsageとFile IOへ進む高い低いのに遅いあるないディスクが疑わしい事象の区間にズームその区間のCPUは?5章: CPU Usage (Sampled)で「誰がどの関数で焼いているか」1コア・1スレッドの張り付きは?6章: CPU Usage (Precise)で「何を待っていたか」7章: Disk Usage / File I/Oで犯人を特定

5. CPUが高い場合 ── CPU Usage (Sampled)で「誰がどの関数で焼いているか」

この章で探すのは、CPU時間の大きな割合を使っている呼び出し経路です。

CPUが張り付いているなら、見るのはCPU Usage (Sampled)です。これは約1ミリ秒ごとに全CPUで「いまどのプロセスのどのスタックが実行中か」を記録したサンプリングデータで、サンプル数の比率がそのままCPU時間の内訳になります。6

CPU Usage Sampledの仕組み約1ミリ秒ごとに全CPUで実行中のスタックを記録し、サンプルを集計した比率がCPU時間の内訳になる。プロセスからスレッド、スタック、関数へ降りて読む。サンプルの合間に終わる短い活動は写らない約1msごとの割り込み全CPUで「いま実行中のスタック」を記録サンプルを集計(比率 = CPU時間の内訳)Process → Thread → Stack → 関数へ降りるサンプルの合間に終わる短い活動は写らない

プロセスからスタック、関数へ降りる

  1. Graph ExplorerのComputationからCPU Usage (Sampled)をAnalysisタブへ置き、プリセットUtilization by Process, Stackを選びます。5
  2. Weight(またはCount)の大きい順にプロセスを見ます。タスクマネージャーで「50%」だったものの正体が、まずプロセス単位で分かります。
  3. 犯人プロセスのStack列を展開していきます。スタックはツリーで集計されており、枝分かれで数字が大きく減らない道を降りていくと、CPUを焼いている関数に着きます。シンボルが解決できていれば、自社コードのどの関数かまで一直線です。
  4. ツリーの展開が煩わしければ、グラフ表示をFlame(炎グラフ)に切り替えます。横幅=CPU時間の割合で描かれるため、どの呼び出し経路が支配的かが一目で分かります。CPU Usage (Sampled)にはFlame by Process, Stackというプリセットも用意されています。13

Sampledでは、1回ごとの正確な時間は測れない

サンプリングである以上、サンプルの合間に終わる短い活動は写りません。6 「合計としてどこがCPUを使ったか」を見る道具であって、1回ごとの正確な実行時間を測る道具ではない、と覚えておいてください。

6. CPUが低いのに遅い場合 ── CPU Usage (Precise)と待ち解析

6.1. 待ち解析の前に、1コアの張り付きを確認する

「全体のCPU使用率が低い」は「CPUがボトルネックではない」を意味しません。 16コアのPCでは、1コアに張り付いたシリアル処理(UIスレッド1本が全力で回っている状態)も、全体では6%程度にしか見えないからです。

まず5章のSampled、またはCPU Usage (Precise)のUtilization by CPUで、特定のコア・スレッドの張り付きがないかを確認します。張り付きもないなら、処理はCPUを使えないのではなく何かを待っていると考えて待ち解析へ進みます。ここから使うのが、CPU Usage (Precise)です。

6.2. 「待っていた時間」と「起きた後のCPU待ち」を分ける

Sampledがサンプリングなのに対し、Preciseはコンテキストスイッチ(スレッドの切り替え)の完全な記録です。スレッドが待ちに入り、誰かに起こされ(Ready)、CPUに載る──この往復が1行ずつ残っており、次の列が読めます。74

列 意味
NewThreadStack そのスレッドがどのスタックで待ちに入ったか(=何をして止まったか)
Waits (us) 待っていた時間
Ready (us) 起こされてからCPUに載るまで待たされた時間(CPU の取り合い)
ReadyingProcess / ReadyingThreadId そのスレッドを起こした(待ちを解いた)プロセスとスレッド
ReadyThreadStack 起こした側がどのスタックで起こしたか
1回の待ちの往復と各列の対応スレッドはNewThreadStackに残るスタックで待ちに入り、Waitsの時間だけ待つ。誰かに起こされるとReadyingProcessとReadyThreadStackにその相手が残り、Readyの時間だけCPUの取り合いを待ってから再び実行される待ちに入る(NewThreadStackに残る)誰かが起こす(ReadyingProcess / ReadyThreadStack)CPUに載る実行中待ち(Waits (us))Ready(CPUの取り合い待ち)再び実行

6.3. 遅延したスレッドから、起こした相手を順に辿る

読み方は、次の順番です。4

1. グラフと列を用意する

プリセットUtilization by Process, Threadを適用し、列にNewThreadStack・ReadyThreadStackを追加します。

2. 遅延した操作のスレッドを選ぶ

まず、UIスレッドや対象リクエストの処理スレッドなど、遅延した操作を実行していたスレッドを特定します。Waits合計の大きい順に見るだけでは、メッセージポンプやタイマーのように、意図的に待ち続ける正常なスレッドが上位に来てしまいます。

対象スレッドのCPU Usage (ms)が大きければ5章のCPU問題、Waitsが支配的なら待ち問題です。

3. NewThreadStackで「何をして止まったか」を見る

NewThreadStackを展開します。WaitForSingleObjectやEnterCriticalSectionならロック待ち、ReadFileなど同期I/Oの中ならI/O待ち、ソケット受信の中なら相手の応答待ちです。

4. ReadyThreadStackで「誰が待ちを解いたか」を見る

ReadyThreadStackを展開し、ReadyingProcess / ReadyingThreadIdを確認します。カーネルのKiTimerExpirationから起こされていればタイマー(タイムアウトまで寝ていた)、I/O完了処理から起こされていればI/O待ちだったことが裏付けられます。4

5. 起こした相手にも、同じ調査を繰り返す

起こした相手が別のスレッドや別のプロセスなら、今度はそのスレッドを同じ手順で調べます。

たとえば、AはBのロック解放を待ち、BはCのRPC応答を待ち、CはディスクI/Oを待っていた、という連鎖です。この鎖を根元まで辿ったものが、遅延のクリティカルパスです。7

待ち解析で辿るクリティカルパスの鎖遅延したスレッドAのNewThreadStackで何をして止まったかを見て、ReadyThreadStackとReadyingProcessで起こした相手Bを特定し、Bも同じ手順で調べて根元のディスクI/Oまで辿るNewThreadStack: ロック待ちで停止NewThreadStack: RPC応答待ちNewThreadStack: 同期I/O待ち完了がCを起こす応答がBを起こすロック解放がAを起こす(ReadyThreadStackに現れる)スレッドA(遅延した操作)スレッドB(ロック保持中)プロセスCディスクI/O(根元)

待ちの原因を、設計の見直しにつなげる

たとえば「マルチスレッド化したのに速くならない」案件では、この手順で1本のロックに全ワーカーが並んでいる様子がそのまま見えます。ロック競合を設計で避ける話は「マルチスレッドの実務ベストプラクティス .NET編」に、同期I/Oで待つ代わりに完了通知で回すWindowsの仕組みは「I/O完了ポート(IOCP)と.NETスレッドプール」に書きました。WPAで「誰を待っていたか」を突き止め、これらの設計論で直す、が一続きの流れです。

7. ディスクとファイルI/O ── 「誰かがディスクを舐めている」を特定する

「PC全体が重い」の定番犯人は、CPUではなくディスクです。StorageカテゴリのDisk UsageとFile I/Oで調べます。15

7.1. Disk Usageで「装置の処理」と「待ち行列」を分ける

Disk UsageはディスクI/Oの記録です。最初に、次の2列を区別します。6

列 表している時間
Disk Service Time ディスク装置が、そのI/Oの処理に実際に掛かった時間
IO Time I/OがOSのキューに入ってから完了するまでの時間

IO Timeは待ち行列の分だけ必ずService Time以上になります。IO TimeがService Timeより大幅に長ければ、そのI/Oは待ち行列で待っていたと分かります。6

ただし、時間差だけで原因を断定しないでください。他のプロセスが列を作ったのか、遅い装置に自分自身の大量I/Oが並んだのかは、まだ決まりません。Service Timeで装置自体の応答を見たうえで、プロセス・パス・スタック別の内訳で確定させます。

7.2. どのプロセスが、どのファイルへI/Oを出したか

そこでUtilization by Process, Path Name, Stackのプリセットで、どのプロセスが・どのファイルに・どのスタックからI/Oを発行したかを、IO TimeやSizeの大きい順に見ます。15 現場でよく出る答えはこの2つです。

  • ウイルス対策ソフトが全ファイルを舐めていた。アプリの起動が遅い時間帯に、対策ソフトのプロセスが大量の読み取りを発行している形で見えます。除外設定の相談材料として、プロセス名・パス・量の証拠がそのまま揃います。
  • 別プロセスが大量書き込みをしていた。バックアップ、インデクサー、ログの書き過ぎなど。書き込みがいつディスクに届くかはキャッシュマネージャーが絡むため、「書いた瞬間」と「ディスクが忙しい瞬間」がずれることも含めて「キャッシュマネージャー ── あなたのWriteFileはいつディスクに届くのか」で解説しています。

7.3. File I/Oで、ディスクに届く前の遅さを見る

File I/Oはもう一段上の層、つまりアプリが発行したファイル操作(Create/Read/Write等)の記録で、Duration by Process, Thread, Typeなどのプリセットでファイル名単位・操作単位の時間を集計できます。15

ディスクに届く前にファイルシステムやフィルタドライバーで時間を食っているケースはDisk Usageに出ないので、「Disk Usageは平和なのにFile I/Oは遅い」という食い違い自体が手掛かりになります。同期I/Oと非同期I/Oの仕組みから知りたい方は「同期I/Oと非同期I/O ── OVERLAPPEDの本当の意味」をどうぞ。

File IOとDisk Usageが見る層の違いアプリのファイル操作はファイルシステムとフィルタドライバーを経てOSのIOキューからディスク装置に届く。File IOは上の層の操作を、Disk Usageはディスクに届いたIOを記録し、IO TimeとDisk Service Timeの差が待ち行列の時間を示すアプリ: ReadFile / WriteFileファイルシステム・フィルタドライバー(File I/Oが見る層)OSのI/Oキューディスク装置(Disk Usageが見る層)ここで時間を食うとDisk Usageには出ないIO Time − Disk Service Time = 待ち行列の時間Disk Service Time = 装置の処理時間

7.4. メモリ不足を疑うときは、物理メモリも確認する

「メモリ不足でスワップしているのでは」という筋は、WPAに進む前にタスクマネージャーとリソースモニターで一次切り分けできます。

コミット済みメモリだけを見て、メモリ不足を否定しないでください。 コミット済みに余裕があっても、物理メモリの逼迫でワーキングセットが削られてハードフォルトが続く状況はあり得ます。利用可能な物理メモリと、リソースモニターの「ハード フォールト/秒」も併せて確認します。読み方は「Windowsの「メモリ使用量」は何を表しているのか」を参照してください。

8. 起動・ログオンが遅い ── ブートトレースの入口

「起動に3分かかる」タイプは、手でwpr -startする前に問題が終わってしまいます。WPRにはブートトレースがあり、次回起動時にOSが自動で記録を開始するよう仕込めます。3

次回起動の記録を仕込み、再起動後に保存する

3章と同様に採取の承認とETLの取り扱いを決め、管理者として開いたコマンドプロンプトで操作します。

:: 1. 次回起動時の自動記録を仕込む
wpr -boottrace -addboot GeneralProfile -filemode

:: 2. 再起動する(起動の遅さを再現)

:: 3. 起動後、記録を止めて保存(仕込みも解除される)
mkdir C:\temp 2>nul
wpr -boottrace -stopboot C:\temp\boot.etl "起動に3分かかる事象"
ブートトレースの流れaddbootで次回起動時の自動記録を仕込んでから再起動すると、起動時にOSが自動で記録を開始する。ログオン後にstopbootで保存すると仕込みも解除される。やめる場合はcancelbootで解除するwpr -boottrace -addboot で仕込む再起動(起動の遅さを再現)起動時にOSが自動で記録開始ログオン後に -stopboot で保存(仕込みも解除)やめるなら -cancelboot

採れた後は、同じ「CPU・待ち・I/O」の切り分けへ

かつてのxbootmgrが担っていた起動・シャットダウンの計測は、現在のWPRでは-onoffscenario Bootなどのオプションでも実行できます。3

採れたトレースは、これまでの章と同じ道具立てで読めます。Processesグラフでどのプロセスがいつ生まれたかを時系列で眺め、起動が詰まっている時間帯にズームして、CPUか・待ちか・ディスクかを分類する──スタートアップアプリが直列に何かを待っている、サービスの開始が特定のI/Oで止まっている、といった形が見えてきます。

ブート解析はそれ自体が深い専門領域なので、この記事では「手動で間に合わない事象もWPRなら採れる」という入口まで。まずGeneralProfileのブートトレースで全体像を掴むところから始めてください。

9. 実務の型 ── 分類→ズーム→スタックの反復

道具が分かったところで、調査全体の型をまとめます。時刻を確定して区間を絞り、分類した後でスタックを辿る順番は、どの症状でも共通です。

時刻の確定から、仮説の検証まで

  1. 現象の時刻を確定する。「重かった」ではなく「10:23:40〜10:24:10が重かった」まで固めます。アプリログ、イベントログ、操作した人のメモ、何でも構いません。自社アプリがETWやイベントログに節目を書いていれば、トレース内のイベントがそのまま時刻の杭になります。
  2. その区間だけにズームする。トレース全体の集計は平均でならされて、肝心の異常が薄まります。WPAの分析は常に「異常だった区間」対「正常だった区間」の比較です。
  3. 「CPUか、待ちか、I/Oか」を最初に分類する。CPU Usage (Sampled)を見て焼けていれば5章へ。焼けていなければCPU Usage (Precise)のWaitsへ(6章)。Disk UsageのIO Timeが膨れていれば7章へ。この三叉路を最初に通ると、迷子になりません。
  4. 仮説→ズーム→スタック、を繰り返す。「ウイルス対策では?」と思ったらそのプロセスに絞り、スタックで裏を取る。外れたら次の仮説へ。スタックまで降りて裏を取る前に結論を出さないのが、この種の調査の規律です。
性能調査の反復ループ現象の時刻を確定して区間にズームし、CPUか待ちかIOかを分類し、仮説を立てて絞り込み、スタックで裏を取る。裏が取れれば原因確定、外れたら次の仮説で繰り返す裏が取れた外れた現象の時刻を確定その区間にズームCPUか・待ちか・I/Oかを分類仮説を立てて絞り込むスタックで裏を取る原因確定 → 対策へ

ETLの取り扱いは、採取前に決める

ETLファイルには、全プロセスの名前、開いたファイルのパス、読み込まれたモジュール、(プロファイルによっては)レジストリのキー名など、システムの内部が広く写っています。

GeneralProfileの標準採取に通信内容のようなデータ本体は含まれませんが、カスタムプロバイダーを有効化した場合は、そのイベントのペイロード(アプリが記録した文字列など)がそのまま入ります。

有効化したプロバイダーが何を出すかまで確認したうえで、社外に出すには十分に機密なファイルとして扱ってください。パケットキャプチャと同じく、必要最小限の採取・渡す相手との合意・保管期限と削除を手順に組み込んでください。

ETLファイルに写るものと取り扱いETLには全プロセス名、開いたファイルのパス、モジュール、プロファイルによってはレジストリキー名が写り、カスタムプロバイダーを有効化するとそのペイロードも入る。機密ファイルとして必要最小限の採取、渡す相手との合意、保管期限と削除を手順化するETLファイル全プロセス名・ファイルパス・モジュール(プロファイルにより)レジストリキー名カスタムプロバイダーのペイロード(アプリが記録した文字列)機密として扱う: 必要最小限の採取・相手との合意・保管期限と削除

10. まとめ

WPR/WPAの調査は、次の3段階で考えると整理できます。

  1. 必要な区間を採る。 Windows 8.1以降に標準搭載されたwpr.exeで採取し、ETLを手元のWPAで読みます。基本はwpr -start GeneralProfile -filemode → 再現 → wpr -stop trace.etl。再現できるならFileモードで数分以内、待ち受けるならMemoryモードです。起動中の遅さにはwpr -boottraceを使います。長く採るほどよいわけではなく、ETLの内部情報は機密として扱います。
  2. 時間帯を絞り、調べる方向を選ぶ。 WPAでは金色バーの左がグルーピング、青色バーの右が集計値です。列の並び・区間のズーム・シンボル設定を押さえ、CPUか、待ちか、I/Oかを切り分けます。自社アプリにはPDBを用意し、.NETのJITコードでは採取時のCLRイベントも確認します。
  3. スタックまで辿って、仮説を確かめる。 CPUが高ければSampledでプロセスから関数へ降ります。全体のCPUが低くても、まず1コア・1スレッドの張り付きを確認し、それもなければPreciseで待ちを追います。ディスクでは時間差だけで原因を決めず、装置の応答とI/Oの発行元の内訳まで見ます。

待ち解析で辿るのは、NewThreadStack(何をして止まったか) → Waits(どれだけ待ったか) → ReadyingProcess・ReadyThreadStack(誰が起こしたか)です。起こした相手も同じように調べると、遅延の連鎖を根元まで追えます。

WPAは、最初は画面の情報量に圧倒されるかもしれません。それでも、「列の並びが集計の切り口」「SampledはCPUを使った場所、Preciseは待った相手」を押さえれば、あとは時刻の確定・ズーム・分類・スタック確認の反復です。次に「CPUは余っているのに遅い」という相談が来たら、この順番でトレースを採り、読み進めてください。

関連記事

関連する相談領域

合同会社小村ソフトでは、「PC全体が重くなったが原因が分からない」「CPUに余裕があるのにアプリが遅い」「特定の環境だけ起動が極端に遅い」といったシステム全体の性能問題の調査を扱っています。WPR/WPAによる採取設計(どの環境で・どのプロファイルを・どれだけ採るか)からトレース解析、原因となったアプリ側・設定側の修正までを一続きで対応します。

参考リンク

  1. Microsoft Learn, Introduction to WPR. WPRがETWベースの性能記録ツールであること、コマンドライン版のWPR.exeがWindows 8.1以降のOSに同梱され追加インストール不要であること、GUI版のWPRUI.exeとの関係、記録プロファイルの考え方について。 ↩ ↩2 ↩3

  2. Microsoft Learn, Windows Performance Analyzer. WPAがWindows ADKに含まれ、WPR・Xperf等が記録したETWイベントからグラフとデータテーブルを作成する解析ツールであり、任意のETLファイルを開いて分析できることについて。 ↩ ↩2 ↩3 ↩4

  3. Microsoft Learn, WPR Command-Line Options. wpr -start/-stop/-cancel/-status/-profilesの構文、-filemode(既定はメモリモード)、複数プロファイルの同時指定、-boottraceによるブートトレース(addboot/stopboot/cancelboot)、-onoffscenarioによるBoot等のOn/Off遷移の記録について。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  4. Microsoft Learn, CPU Analysis. CPU Usage (Precise)グラフの列(NewThreadStack・ReadyThreadStack・ReadyingProcess・Waits等)の定義と、ReadyThreadStackを展開してReadyingProcess/ReadyingThreadを辿り待ちの根本原因に到達する手順、KiTimerExpiration(タイマー待ち)やI/O完了による起床の見分け方について。 ↩ ↩2 ↩3 ↩4 ↩5

  5. Microsoft Learn, Troubleshoot processes and threads by using WPR and WPA. 高CPU使用時にCPU Usage (Sampled)をProcess→Stackで読む構成、待ち解析(Wait analysis)でCPU Usage (Precise)のReadying Process・Readying Thread・Readying StackとWait列を使う構成など、症状別のプロファイルとグラフの対応表について。 ↩ ↩2

  6. Microsoft Learn, Exercise 2 - Evaluate Fast Startup Using Windows Performance Toolkit. CPU Usage (Sampled)が約1ミリ秒間隔のサンプリングでありサンプル間の短い活動は記録されないこと、プロセス→スレッド→スタックと降りてCPU消費の内訳を特定する手順、Disk UsageのIO Time(キュー時間を含む)とDisk Service Time(ディスクの処理時間)の意味について。 ↩ ↩2 ↩3 ↩4 ↩5

  7. Microsoft Learn, Exercise 3 - Understand Critical Path and Wait Analysis. クリティカルパス解析の考え方(Running・Ready・Waitingの分類)、CPU Usage (Precise)テーブルのNewThreadStack・ReadyThreadStack・ReadyingProcess・Waits・Ready等の列の意味、起こした側のスレッドを順に辿って遅延の連鎖を解明する手順について。 ↩ ↩2 ↩3

  8. Microsoft Learn, Loading Symbols. _NT_SYMBOL_PATH未設定時にWPAがMicrosoft公開シンボルサーバー(msdl.microsoft.com)を既定で参照すること、自社コンポーネントのPDBパスの追加、WPRが.NETのマネージドシンボル用PDBをトレースの隣の.ngenpdbフォルダーに生成しWPAが自動参照することについて。 ↩ ↩2 ↩3

  9. Microsoft Learn, Built-in Recording Profiles. WPRに組み込まれた記録プロファイルの一覧(CPU usage、Disk I/O activity、File I/O activity、Registry I/O activity、Networking I/O activityほか)と各プロファイルが記録する内容について。 ↩

  10. Microsoft Learn, Logging Mode. 記録モードにFile(連続ファイル)とMemory(メモリ上の循環バッファ)があり既定がMemoryであること、Memoryはいつ起きるか分からない事象向きで古いイベントが上書きされること、Fileはディスク空き容量が唯一の上限で大きすぎるファイルはWPAで解析できないことがあることについて。 ↩ ↩2

  11. Microsoft Learn, WPR How-to Topics. WPRUIでの記録の開始・停止手順、プロファイル・詳細レベル・Logging modeの選択、長時間の記録ではファイルが巨大化しWPAで解析できないことがあるためMemoryモードを選ぶべきという注意について。 ↩ ↩2

  12. Microsoft Learn, Graph Explorer. Graph ExplorerウィンドウにSystem Activity・Computation・Storage・Memory等のカテゴリでグラフのサムネイルが並ぶこと、グラフをAnalysisタブへドラッグして表とともに表示することについて。 ↩

  13. Microsoft Learn, Graphs (WPA Features). WPAのFlame(炎グラフ)表示、金色バーの左の列がグルーピング・青色バーの右が集計値というテーブル構成、CPU Usage (Sampled)のFlame by Process, Stackプリセットについて。 ↩ ↩2

  14. Microsoft Learn, Load Symbols or Configure Symbol Paths. WPAのTraceメニューからLoad Symbolsでシンボルを読み込むこと、Configure Symbol Pathsダイアログでシンボルパスを設定・変更する手順について。 ↩

  15. Microsoft Learn, List of WPA Graphs. WPAで使えるグラフの一覧。Disk UsageのIO Time by Process, IO Type・Service Time by Process, Path Name, Stack・Utilization by Process, Path Name, Stack、File I/OのDuration by Process, Thread, Type等のプリセットについて。 ↩ ↩2 ↩3

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

この記事は次のサービスページにつながります。近い入口からご覧ください。

よくある質問

この記事のテーマについて、相談時によくある質問をまとめています。

WPRとWPAはどこで入手できますか?インストールできない顧客環境でも使えますか?
採取ツールのwpr.exe(コマンドライン版)はWindows 8.1以降のOSに標準搭載されており、追加インストールなしで使えます。GUI版のWPRUIと、解析ツールのWPA(Windows Performance Analyzer)はWindows ADK(Windows Assessment and Deployment Kit)に含まれており、こちらは別途インストールが必要です。実務では「顧客環境ではOS標準のwpr.exeだけでETLファイルを採取し、持ち帰って手元のWPAで解析する」という分担にすれば、ソフトを追加できない現場でもシステム全体の性能調査ができます。
タスクマネージャーでCPUに余裕があるのに遅いのはなぜですか?WPAで何が分かりますか?
CPU使用率が低いのに遅い場合、処理はCPUを使えないのではなく「何かを待って」止まっています。ロックの取り合い、同期I/Oの完了待ち、他プロセスの応答待ちなどが典型です。タスクマネージャーは使用率という結果しか見せませんが、WPAのCPU Usage (Precise)はコンテキストスイッチ単位の記録から、スレッドがどこで待ち始め(NewThreadStack)、どれだけ待ち(Waits)、誰に起こされたか(ReadyingProcess・ReadyThreadStack)まで示します。待たせた相手を順に辿ることで、「遅さの犯人」を関数レベルで特定できます。
トレースはどのくらいの時間採ればよいですか?ファイルが巨大になりませんか?
事象を再現できるなら、再現の直前に開始して直後に停止し、数分以内に収めるのが基本です。WPRの既定はメモリ上の循環バッファに記録するMemoryモードで、古いイベントから上書きされるため、いつ起きるか分からない事象の待ち受けに向きます。-filemodeを付けるFileモードは連続したファイルに全部残る反面、上限はディスク空き容量だけで、大きすぎるファイルはWPAで解析できなくなることがあります。長時間の待ち受けはMemoryモード、短時間の確実な再現はFileモード、と使い分けてください。
PerfViewとWPAはどう使い分けますか?
どちらもETWトレースを扱うツールですが、得意分野が違います。PerfViewは.NETランタイムの理解が深く、GC・アロケーション・JITなどマネージドアプリ固有の調査に強いツールです。WPAはOS全体のCPU・ディスク・ファイルI/O・電源などをグラフとテーブルで横断的に読むのに向いており、「特定アプリではなくPC全体が重い」「複数プロセスが絡む」「アプリの外(ウイルス対策、ドライバー、他プロセス)が疑わしい」場合の本命です。自社の.NETアプリ単体の遅さはPerfView、システム全体の遅さはWPR/WPA、が目安です。
顧客の本番環境でWPRを動かしても大丈夫ですか?
短時間の採取なら実務上よく行われますが、無条件に安全ではありません。ETWは軽量とはいえ、スタック付きのイベントを大量に記録するため、CPUとメモリを一定量消費します。再現操作の直前に開始して直後に停止する、採取は数分以内に収める、業務への影響が少ない時間帯に実施する、といった配慮を通常の変更作業と同じ承認プロセスに乗せてください。また、ETLファイルにはプロセス名・ファイルパス・実行ファイルの情報などシステムの内部情報が含まれるため、社外へ持ち出す際の取り扱い(最小化・保管期限・削除)もあらかじめ決めておくべきです。

著者プロフィール

記事の著者プロフィールページです。

小村 豪

合同会社小村ソフト 代表

Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。

ブログ一覧に戻る