WPR/WPA 实务 ── 从系统整体调查「整台 PC 变慢」

· · Windows, 性能, WPR, WPA, ETW, 性能排查, 故障排查, Windows 开发

「他们说装了新应用之后整台 PC 就变慢。可是看任务管理器,CPU 和内存都还有余裕。」「有一台 PC 开机要 3 分钟。完全不知道哪里不对。」── 性能咨询真的常常是这种形状。共通点是:只盯着特定进程得不到答案

进程层级的工具已经齐备。文件与注册表访问可用 Process Monitor 看到,.NET 应用的 CPU 与 GC 可用 PerfView 追。但「整台 PC 变慢」或「CPU 闲着却还是慢」这种症状,一开始连哪个进程是元凶都不知道。应用 A 变慢,可能是杀毒扫描、可能是另一个服务猛写磁盘,也可能是跨好几个进程的锁链。你需要的是不是进程内部、而是把整个 OS 记在同一条时间轴上的数据

采集并读取那份数据的工具,就是 Windows Performance Recorder(WPR)与 Windows Performance Analyzer(WPA)。WPR 以 ETW(Event Tracing for Windows)为基础记录整个 OS 的活动,WPA 用图表与表格分析那份纪录。谁在哪个调用栈用了 CPU、线程在等谁、哪个进程对哪个文件发出磁盘 I/O──比任务管理器再往下一两层的事实,都带着时间戳留下来。

本文以中小企业的 IT 人员与 Windows 应用开发者为对象,依 2026 年 8 月的第一手资料,整理用 WPR 采集的实务,以及怎么读 WPA──尤其是调查「CPU 很高」与「CPU 很低却还是慢」的差异。

1. 先说结论

  • 「整台 PC 变慢」调查的首选是采集并读取整个 OS 的 ETW 追踪的 WPR/WPA。进程层级工具(任务管理器、Procmon、PerfView)钉不住的问题,只要把每个进程与内核放在同一条时间轴上就能追。12
  • 采集工具 wpr.exe 从 Windows 8.1 起就内建。不必另外安装。GUI 版(WPRUI)与分析工具 WPA 包含在 Windows ADK 里。12
  • 基本步骤就三行。以系统管理员执行 wpr -start GeneralProfile -filemode → 复现问题 → wpr -stop C:\temp\trace.etl。只记住这个就能开始采集。3
  • 现场基准是拆成「在客户现场只用 wpr.exe 采集;阅读在自己机器上用 WPA」。即使不能安装软件的服务器也能采集。想法和数据包捕获的「用标准工具采集、用 Wireshark 读」一样。1
  • 读 WPA 从分类「CPU、等待、还是 I/O」开始。CPU 在烧就看 CPU Usage (Sampled);CPU 闲着却还是慢就做 CPU Usage (Precise) 的等待分析;怀疑磁盘就看 Disk Usage──路径一开始就分叉。45
  • CPU Usage (Sampled) 以大约每 1 毫秒的取样,显示「哪个函数用了 CPU」。可以把任务管理器那个「50%」从进程 → 线程 → 调用栈 → 函数拆开。6
  • CPU Usage (Precise) 是上下文切换的完整纪录,告诉你「线程在等谁」。走 Waits(等待时间)、ReadyingProcess(谁叫醒它)、ReadyThreadStack(叫醒者的调用栈),是本文最想传达的手法。47
  • 读调用栈需要符号设置。WPA 默认会引用 Microsoft 的公开符号服务器。要看到自己应用的函数名称,请加上自己的 PDB 路径。8
  • ETL 文件含有进程名称与文件路径等系统内部信息。采集只做到必要的最小量,并在采集前决定若带出公司要怎么处理。

2. 工具各司其职 ── WPR 采集,WPA 读

Windows Performance Toolkit(WPT)是 Windows ADK(Windows Assessment and Deployment Kit)里的性能排查工具组;核心是 WPR 与 WPA 这一对。2 角色分得很清楚。

  • WPR(Windows Performance Recorder)=采集。它把一组 ETW 提供者捆成称为「配置文件」的单位,开始与停止记录,产出 ETL 文件。命令行版 wpr.exe 从 Windows 8.1 起就内建,不必另外安装。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 文件;带回来在自己已透过 ADK 安装 WPA 的 PC 上分析自己的 PC(经 ADK 的 WPA)客户 PC(不必另外安装)带回来分析图表与表格ETL 文件wpr start → 复现 → stop

图 1: 在客户现场用 OS 标准的 wpr.exe 记录并产出 ETL 文件;带回来在自己已透过 ADK 安装 WPA 的 PC 上分析。

和相近工具的差异,也值得先整理。

  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

在系统管理员终端机里的基本步骤。

:: List of built-in profiles you can use
wpr -profiles

:: 1. Start capture (general-purpose profile, file mode)
wpr -start GeneralProfile -filemode

:: 2. Reproduce the issue (check capture status with wpr -status)

:: 3. Stop and save (you can attach a description of the problem).
::    Create the destination folder in advance (without it, -stop fails to save)
mkdir C:\temp 2>nul
wpr -stop C:\temp\slow-pc.etl "Reproduced the issue where the whole PC becomes slow while starting App X"

:: To abandon without saving
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 采集流程与模式怎么选当场能复现的问题用文件模式短而可靠地采集;时机不明的问题用默认的内存模式环形缓冲区等待。开机或登录时的问题用开机追踪。无论哪种,start/复现/stop 的步骤相同当场时机不明开机或登录何时发生?文件模式:短采集内存模式:等待(3.1)开机追踪(第 8 章)start → 复现 → stop

图 2: 当场能复现的问题用文件模式短而可靠地采集;时机不明的问题用默认的内存模式环形缓冲区等待。开机或登录时的问题用开机追踪。无论哪种,start/复现/stop 的步骤相同。

3.1. Memory 模式与 File 模式 ── 能复现,还是要等

WPR 有两种记录目的地模式;默认是 Memory 模式(内存内的环形缓冲区)。它是从最旧事件开始覆盖的环形缓冲区,适合让采集持续跑、等时机不明的问题发生、发生时再停。加上 -filemode 就切到 File 模式,一切写进连续文件。这个不会被覆盖掉;上限只剩剩余磁盘空间,文件会无限成长。10

Memory 模式与 File 模式怎么记录Memory 模式写入内存内的环形缓冲区;较旧的事件被覆盖、只留下最近的,因此适合等待。File 模式把一切留在文件里,但上限只剩剩余磁盘空间,因此适合短而可靠的复现ETW 事件Memory 模式:环形缓冲区File 模式:让文件成长等时机不明的问题短而可靠的复现

图 3: Memory 模式写入内存内的环形缓冲区;较旧的事件被覆盖、只留下最近的,因此适合等待。File 模式把一切留在文件里,但上限只剩剩余磁盘空间,因此适合短而可靠的复现。

选择的经验法则如下。

  • 当场能复现 → File 模式。复现前一刻开始、刚结束就停,把采集控制在几分钟内
  • 时机不明 → 用 Memory 模式(默认)等待。一发生就 wpr -stop
  • 即使只是几分钟的 GeneralProfile,也可能产出数百 MB 到 GB 级的 ETL。文件太大时 WPA 可能无法分析,所以「采集得愈久愈好」会适得其反1011

要用 GUI 采集,启动 WPRUI,选配置文件与 Logging mode,再 Start/Save。官方 How-to 整理了步骤。11 若请客户现场窗口采集,上面三条指令可以直接写进程序。

4. 读 WPA 的基础 ── 图表、表格黄金法则、缩小时间范围

把采集到的 ETL 在 WPA 打开后,左侧的 Graph Explorer 会依 System Activity、Computation、Storage、Memory 等分类列出图表缩图。12 把想看的图表拖到右侧 Analysis 选项卡,上方出现图、下方出现表。先掌握这三件事。

  1. 表格的黄金法则──列顺序决定分组。WPA 表格有金、蓝两条垂直线,金线左侧的列依该顺序把数据阶层化(分组),蓝线右侧的列是汇总13 排成 Process → Stack 就得到依进程的调用栈汇总;Stack → Process 就得到使用同一调用栈的每个进程的汇总──拖曳列重新排序本身就是分析操作。懂这一点,每张 WPA 表格都用同一种读法。
表格的黄金法则──两条线与列角色金线左侧的列依该顺序把数据阶层化;金线与蓝线之间是显示栏;蓝线右侧是汇总。拖曳列重新排序本身就是分析操作金线左侧:分组金线两线之间:显示蓝线蓝线右侧:汇总拖曳列来分析

图 4: 金线左侧的列依该顺序把数据阶层化;金线与蓝线之间是显示栏;蓝线右侧是汇总。拖曳列重新排序本身就是分析操作。

  1. 缩小时间范围。在图上拖曳选范围,再右键「Zoom」,汇总就只切到该区间。性能排查原则上永远只看「问题正在发生的区间」(第 9 章)。
  2. 设置符号。要用函数名称读调用栈,从菜单执行 Trace > Load Symbols14 默认会引用 Microsoft 的公开符号服务器(msdl.microsoft.com),所以有网络连线就能解析 Windows 自己的调用栈。要看到自己应用的函数名称,在 Trace > Configure Symbol Paths 加上自己应用的 PDB 文件夹。8 PDB 是什么、为什么即使 Release 构建也该一律保留,整理在〈PDB(程序数据库)是什么〉。对 .NET Framework 的 NGen 原生映像,WPR 在采集时会产生 NGen PDB(.ngenpdb)并放在追踪旁边的文件夹,WPA 会自动引用。8 这只是 NGen 映像的机制,一般自己的 JIT .NET 应用码不在范围内。从 JIT 代码位址到函数名称的对应,是从 CLR 发出的 JIT 事件解析的,因此调查 .NET 应用时,请准备启用 CLR 提供者(Microsoft-Windows-DotNETRuntime 与对应的 Rundown)的记录配置文件(.wprp),并用和第 3 章自己的提供者相同的方式组合,wpr -start GeneralProfile -start MyDotNet.wprp!profile-name,让 CLR 事件进追踪(可用 wpr -profiles 确认本机 WPR 提供哪些内建配置文件)。除此之外,保留构建产生的 PDB 以便对应到源代码行,并加到上面的符号路径。
用函数名称读调用栈的符号解析执行 Trace Load Symbols 后,Windows 本身从 Microsoft 公开符号服务器解析,自己的应用从加到符号路径的构建 PDB 解析。NGen 映像使用 WPR 产生的 NGen PDB;JIT .NET 代码从追踪里的 CLR JIT 事件加上构建 PDB 解析Trace > Load SymbolsWindows:公开符号自己的应用:构建 PDBNGen:WPR .ngenpdbJIT:CLR 事件 + PDB

图 5: 执行 Trace Load Symbols 后,Windows 本身从 Microsoft 公开符号服务器解析,自己的应用从加到符号路径的构建 PDB 解析。NGen 映像使用 WPR 产生的 NGen PDB;JIT .NET 代码从追踪里的 CLR JIT 事件加上构建 PDB 解析。

准备好之后,从下一个分支进入。在那个区间,CPU 是高还是低?高就第 5 章(Sampled);低却还是慢就第 6 章(Precise)。

依症状选择 WPA 图表的分支缩放到问题区间;CPU 高就到 CPU Usage Sampled;低却还是慢,先确认是否单核/单线程钉住,再做 CPU Usage Precise 的等待分析;怀疑磁盘就看 Disk Usage 与 File IO低却还是慢怀疑磁盘缩放到问题区间该区间的 CPU?第 5 章:Sampled单核/单线程钉住?第 6 章:Precise第 7 章:磁盘/文件 I/O

图 6: 缩放到问题区间;CPU 高就到 CPU Usage Sampled;低却还是慢,先确认是否单核/单线程钉住,再做 CPU Usage Precise 的等待分析;怀疑磁盘就看 Disk Usage 与 File IO。

5. CPU 很高时 ── 用 CPU Usage (Sampled) 看「谁在烧哪个函数」

CPU 被钉住时,看的是 CPU Usage (Sampled)。这是大约每 1 毫秒在每颗 CPU 上记录「现在哪个进程的哪个调用栈在跑」的取样数据,样本数比例就是 CPU 时间的拆解。6

CPU Usage Sampled 怎么运作大约每 1 毫秒记录每颗 CPU 上正在跑的调用栈,汇总后的样本比例就是 CPU 时间的拆解。从进程读到线程、调用栈、函数。样本之间就结束的短活动不会出现大约每 1 ms 中断记录正在跑的调用栈样本比例 = CPU 拆解进程 → 线程 → 调用栈样本之间的活动会漏掉

图 7: 大约每 1 毫秒记录每颗 CPU 上正在跑的调用栈,汇总后的样本比例就是 CPU 时间的拆解。从进程读到线程、调用栈、函数。样本之间就结束的短活动不会出现。

  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

有一个注意。因为是取样,样本之间就结束的短活动不会出现6 把它记成看「整体上 CPU 用在哪里」的工具,不是量每次呼叫精确持续时间的工具。

6. CPU 很低却还是慢 ── CPU Usage (Precise) 与等待分析

这是本文的核心。不过在进入等待分析之前,先确认一件事。「整体 CPU 使用率低」不代表「瓶颈不是 CPU」。在 16 核 PC 上,钉在单核的序列工作(单一 UI 线程全力跑)整体看起来只有约 6%。先用第 5 章的 Sampled(或 CPU Usage (Precise) 的 Utilization by CPU)确认没有特定核心或线程被钉住,若没有,再到这一章──工作不是跑不了,而是在等。告诉你它在等什么的,是 CPU Usage (Precise)

Sampled 是取样,Precise 则是上下文切换(线程切换)的完整纪录。线程进入等待、被谁叫醒(Ready)、落到 CPU──这一趟来回每列留下一行,你可以读以下列。74

意义
NewThreadStack 该线程在哪个调用栈进入等待(=停下时在做什么)
Waits (us) 等了多久
Ready (us) 从被叫醒到落到 CPU,被让它等多久(CPU 竞争)
ReadyingProcess / ReadyingThreadId 叫醒该线程(解除等待)的进程与线程
ReadyThreadStack 叫醒者在哪个调用栈叫醒它
一次等待来回与列如何对应线程在留在 NewThreadStack 的调用栈上进入等待,等 Waits 的时间。有人叫醒它时,那一方留在 ReadyingProcess 与 ReadyThreadStack;它再等 Ready 时间的 CPU 竞争,然后再跑进入等待有人叫醒它落到 CPU执行中等待(Waits us)Ready(CPU 竞争)再次执行NewThreadStack/ReadyingProcess

图 8: 线程在留在 NewThreadStack 的调用栈上进入等待,等 Waits 的时间。有人叫醒它时,那一方留在 ReadyingProcess 与 ReadyThreadStack;它再等 Ready 时间的 CPU 竞争,然后再跑。

读法如下。4

  1. 套用 Utilization by Process, Thread 默认,并把 NewThreadStack 与 ReadyThreadStack 加到列。
  2. 先找出正在执行延迟操作的线程(UI 线程、处理该请求的线程)。只依总 Waits 由大到小看会混乱,因为消息回圈或计时器这类「刻意一直在等」的线程会占据顶端。找到目标线程后,若它的 CPU Usage (ms) 很大就是第 5 章的 CPU 问题;若 Waits 占主导就是等待问题。
  3. 展开 NewThreadStack,看停下时在做什么WaitForSingleObjectEnterCriticalSection 是锁等待;在 ReadFile 这类同步 I/O 里是 I/O 等待;在套接字接收里是在等对端回应。
  4. 接著看谁解除了等待。展开 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锁等待RPC 等待同步 I/O 等待完成叫醒 C回应叫醒 B放锁叫醒 A线程 A(延迟的工作)线程 B(握着锁)进程 C磁盘 I/O(根)

图 9: 从延迟线程 A 的 NewThreadStack 看出停下时在做什么,从 ReadyThreadStack 与 ReadyingProcess 找出叫醒者 B,再用同一套步骤调查 B,直到根上的磁盘 I/O。

在「我们多线程了却没变快」这种案例,这套步骤会把每个工作者都排在同一把锁上原样显示出来。从设计上避开锁竞争,写在〈多线程的实务最佳实践 .NET篇〉;不在同步 I/O 里等待、而是依完成通知执行的 Windows 机制,写在〈I/O 完成埠(IOCP)与 .NET 线程集区〉。在 WPA 里钉下「它在等谁」,再用那些设计论点修,是一连贯的流程。

7. 磁盘与文件 I/O ── 找出「有人在扫磁盘」

「整台 PC 变慢」的经典元凶不是 CPU 而是磁盘。用 Storage 分类里的 Disk Usage 与 File I/O 调查。15

Disk Usage 是磁盘 I/O 的纪录,有两个列重要。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(装置本身的回应)以及接下来依进程、路径、调用栈的拆解来定案。

接著,用 Utilization by Process, Path Name, Stack 默认,依 IO Time 或 Size 由大到小看哪个进程从哪个调用栈对哪个文件发出 I/O。15 现场常出现的答案是这两种。

  • 杀毒正在扫每个文件。在应用启动变慢的窗口里,看到杀毒进程发出大量读取。进程名称、路径、数量本身就是讨论排除清单的证据。
  • 另一个进程正在猛写。备份、索引器、写太多的日志等。写入何时到达磁盘牵涉快取管理员,因此「你写的那一刻」与「磁盘忙碌的那一刻」可能岔开,这一点也写在〈快取管理员──你的 WriteFile 究竟何时送达磁盘〉。

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──OVERLAPPED 的真正含义〉。

File IO 与 Disk Usage 看到的不同层应用的文件操作经文件系统与筛选驱动,从 OS I/O 队列走到磁盘装置。File IO 记录上层操作;Disk Usage 记录到达磁盘的 I/O;IO Time 与 Disk Service Time 的差是队列时间应用:ReadFile/WriteFile文件系统与筛选器(File I/O)OS I/O 队列磁盘装置(Disk Usage)Disk Usage 看不到IO Time − Service TimeService Time = 装置

图 10: 应用的文件操作经文件系统与筛选驱动,从 OS I/O 队列走到磁盘装置。File IO 记录上层操作;Disk Usage 记录到达磁盘的 I/O;IO Time 与 Disk Service Time 的差是队列时间。

「说不定是内存不够在换页」这条思路,可以在进 WPA 之前先用任务管理器与资源监视器做第一道隔离。不过不要只看认可内存就排除──即使认可还有余裕,实体内存压力裁切工作集、硬错误持续发生的情况仍可能。也要看可用实体内存与资源监视器的「Hard Faults/sec」。怎么读写在〈Windows 的「内存使用量」代表什么〉。

8. 开机与登录很慢 ── 开机追踪的入口

「开机要 3 分钟」这类,还没来得及亲手跑 wpr -start 就结束了。WPR 有开机追踪,可以安排 OS 在下次开机时自动开始记录。3

:: 1. Arrange automatic recording on the next boot
wpr -boottrace -addboot GeneralProfile -filemode

:: 2. Restart (reproduce the slow boot)

:: 3. After boot, stop recording and save (the arrangement is also cleared)
mkdir C:\temp 2>nul
wpr -boottrace -stopboot C:\temp\boot.etl "Issue where boot takes 3 minutes"
开机追踪流程用 addboot 安排下次开机自动记录并重新启动后,OS 在开机时自动开始记录。登录后用 stopboot 保存也会清除安排。要放弃,用 cancelboot 清除wpr -boottrace -addboot重新启动(慢开机)OS 在开机时记录登录后:-stopboot放弃:-cancelboot

图 11: 用 addboot 安排下次开机自动记录并重新启动后,OS 在开机时自动开始记录。登录后用 stopboot 保存也会清除安排。要放弃,用 cancelboot 清除。

以前 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/等待/I/O、形成假设并缩小范围、用调用栈佐证。站得住就确认原因;站不住就用下一个假设再来站得住站不住钉下时间缩放到该区间分类 CPU/等待/I/O假设并缩小范围用调用栈佐证原因确认

图 12: 钉下现象时间、缩放到区间、分类 CPU/等待/I/O、形成假设并缩小范围、用调用栈佐证。站得住就确认原因;站不住就用下一个假设再来。

最后是采集文件的处理。ETL 文件广泛反映系统内部:每个进程的名称、打开过的文件路径、加载的模块,以及(依配置文件而定)注册表项名称。标准 GeneralProfile 采集不含通信内容这类数据本体,但若启用了自定义提供者,该事件的有效负载(应用记录的字符串等)会原样进去。确认你启用的提供者会发出什么之后,把它当成机密到足以带出公司的文件来对待。和数据包捕获一样,把必要的最小采集、与交接对方的约定、以及保存期限与删除写进程序。

ETL 文件反映什么、以及怎么处理ETL 反映每个进程名称、打开过的文件路径、模块,以及依配置文件而定的注册表项名称;启用自定义提供者也会含其有效负载。当成机密:必要的最小采集、与对方的约定、以及保存期限与删除ETL 文件名称、路径、模组注册表项(部分)自订承载当成机密对待

图 13: ETL 反映每个进程名称、打开过的文件路径、模块,以及依配置文件而定的注册表项名称;启用自定义提供者也会含其有效负载。当成机密:必要的最小采集、与对方的约定、以及保存期限与删除。

10. 总结

  • 任务管理器解释不了的「整台 PC 变慢」,用整个 OS 的 ETW 追踪调查──用 WPR 采集、用 WPA 读。wpr.exe 从 Windows 8.1 起就内建,因此「在客户现场采集、把 ETL 带回来、在自己机器上用 WPA 读」这种拆法成立。
  • 采集是 wpr -start GeneralProfile -filemode → 复现 → wpr -stop trace.etl 三步。能复现就用几分钟内的 File 模式;要等就用 Memory 模式(环形缓冲区)。愈长愈好并不成立。
  • 掌握三点就能开始用 WPA:表格黄金法则(金线左侧=分组)、缩放时间范围、符号设置(自己的应用需要 PDB)。
  • CPU 高,就在 CPU Usage (Sampled) 走进程 → 调用栈 → 函数。CPU 低却还是慢,就在 CPU Usage (Precise) 把 NewThreadStack(停下时在做什么)→ Waits(等了多久)→ ReadyingProcess 与 ReadyThreadStack(谁叫醒它)这条链走到根。
  • 对磁盘,从 Disk Usage 的 IO Time 与 Service Time 之差看出「花在队列里的时间」,再从 Service Time 与依进程、路径、调用栈的拆解找出原因(是装置本身慢,还是谁让队列堆起来)。慢开机可用 wpr -boottrace 采集。
  • 实践模式是(1)钉下时间(2)缩放到区间(3)分类 CPU、等待或 I/O(4)反复假设 → 缩放 → 调用栈。ETL 含内部信息,当成机密对待。

WPA 的画面令人却步,每个人第一个小时都会迷路。不过一旦「金线左侧是分组」与「Sampled 是烧在哪、Precise 是等谁」这两根主轴进去,其余就是同一套操作反复做。下次再接到「CPU 还有余裕却还是慢」的咨询,关掉任务管理器,采集一份追踪。

相关文章

相关咨询领域

小村软件有限公司承接「整台 PC 变慢、不知道为什么」「CPU 还有余裕、应用却还是慢」「只有特定环境开机极慢」这类系统整体性能问题的调查。我们把 WPR/WPA 的采集设计(在哪个环境、哪个配置文件、采集多少)、追踪分析,以及随之而来的应用侧与设置侧修正,当成一连贯的委托来处理。

参考链接

  1. Microsoft Learn, Introduction to WPR. 关于 WPR 是以 ETW 为基础的性能记录工具;关于命令行版 WPR.exe 从 Windows 8.1 起就内建、不必另外安装;它与 GUI 版 WPRUI.exe 的关系;以及记录配置文件的想法。  2 3 4

  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 这类开/关转换。  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,以及等待分析时使用 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

  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 托管符号在追踪旁边的 .ngenpdb 文件夹产生 PDB、WPA 自动引用。  2 3

  9. Microsoft Learn, Built-in Recording Profiles. 关于 WPR 内建记录配置文件的清单(CPU 使用、磁盘 I/O 活动、文件 I/O 活动、注册表 I/O 活动、网络 I/O 活动等)以及各配置文件记录什么。 

  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 起就内建,不必另外安装。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 文件含有进程名称、文件路径、可执行文件信息等系统内部信息,若要带出公司,应事先决定怎么处理(最小化、保存期限、删除)。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表