Windows 性能工具
目录
- 一、概览
- 1.1 性能工具分类
- 1.2 工具选择建议
- 1.3 业界成熟工具概览
- 二、内存工具
- 2.1 tcmalloc
- 2.2 UMDH
- 2.3 CRTDBG
- 2.4 句柄泄露检测
- 2.5 AddressSanitizer (ASan)
- 2.6 Dr. Memory
- 三、CPU 工具
- 3.1 WPT (Windows Performance Toolkit)
- 3.2 Very Sleepy
- 3.3 AMD uProf
- 3.4 Windows 性能打点
- 3.5 采集堆栈格式
- 四、符号还原
- 4.1 符号下载
- 4.2 Dia2Dump
- 4.3 WinDbg 符号命令
一、概览
1.1 性能工具分类
| 工具类型 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 检测式剖析器 | 在源代码里面插入性能测量代码 | 精准、数据完整 | 1. 侵入式 2. 改变程序的运行时行为 3. 需要重新编译 |
| 采样型剖析器 | 周期性地捕捉程序当前调用堆栈的快照 | 非侵入式、无需重新编译 | 1. 可能漏采样 2. 数据量大 3. 精度相对较低 |
1.2 工具选择建议
按问题类型选择:
- 系统级问题(驱动、电源、多进程交互):WPT + WPA、PerfView
- 应用性能问题(UI 响应、数据库调用):Visual Studio Profiler、PerfView(.NET)
- 内存问题:AddressSanitizer、Dr. Memory、UMDH、VMMap
- CPU 热点分析:Very Sleepy、Intel VTune、WPT
- GPU 性能问题:NVIDIA Nsight、AMD uProf
- 崩溃分析:ProcDump、WinDbg
- 实时监控:Resource Monitor、Process Explorer、HWiNFO
- 企业级监控:SCOM、Datadog、SolarWinds
按使用阶段选择:
- 开发阶段:Visual Studio Profiler、AddressSanitizer、Very Sleepy
- 测试阶段:Dr. Memory、WPT、PerfView
- 生产环境:PerfView、ProcDump、企业监控工具
- 问题诊断:WPT、Process Monitor、ProcDump
按性能开销选择:
- 低开销:UMDH、CRTDBG、Resource Monitor、Process Explorer
- 中等开销:Dr. Memory、WPT(轻量配置)
- 高开销:AddressSanitizer、WPT(完整配置)
1.3 业界成熟工具概览
Windows 官方工具
| 工具名称 | 类型 | 主要功能 | 适用场景 | 优势 | 局限 |
|---|---|---|---|---|---|
| Windows Performance Toolkit (WPT) | 系统级分析 | 包含 WPR(录制)和 WPA(分析),基于 ETW 事件追踪 | 系统级性能问题、驱动问题、多进程交互 | 功能强大、支持自定义配置、可追踪驱动和硬件事件 | 学习曲线陡峭、数据量大、资源消耗高 |
| PerfView | 应用级分析 | .NET 应用性能分析、GC 分析、内存分析 | .NET 应用性能调优、托管代码分析 | 对 .NET 深入支持、跨进程追踪、轻量级 | UI 不够直观、非 .NET 支持有限 |
| Visual Studio Performance Profiler | 开发工具集成 | CPU、内存、GPU 性能分析 | 开发阶段性能优化、UI 渲染分析 | IDE 集成好、启动快速、用户友好 | 系统层面问题支持有限 |
| Performance Monitor (PerfMon) | 实时监控 | 性能计数器监控、数据收集 | 长期趋势分析、系统稳定性监控 | Windows 自带、支持大量计数器、可定时采集 | 复杂问题难以深入、日志管理复杂 |
| Resource Monitor (Resmon) | 实时监控 | CPU、内存、磁盘、网络实时查看 | 快速定位资源瓶颈 | 界面直观、实时性强 | 功能相对简单 |
| Process Explorer | 进程诊断 | 进程树、句柄、DLL、线程信息 | 进程级问题诊断、资源占用分析 | 比任务管理器更深入、功能强大 | 需要一定学习成本 |
| Process Monitor (ProcMon) | 系统行为追踪 | 文件系统、注册表、进程线程活动追踪 | 文件/注册表访问问题排查 | 实时捕获、强大筛选功能 | 数据量大、需要筛选技巧 |
| ProcDump | 崩溃诊断 | 进程 Dump 捕获(CPU 峰值、异常等) | 崩溃分析、异常情况捕获 | 触发条件灵活、命令行友好 | 仅捕获瞬间状态、需要后续分析 |
Sysinternals 工具集
| 工具名称 | 主要功能 | 适用场景 |
|---|---|---|
| VMMap | 进程虚拟/物理内存分析 | 内存占用分析、内存泄漏定位 |
| Sysmon | 系统安全事件日志记录 | 安全审计、行为分析 |
| TCPView | TCP/UDP 连接状态查看 | 网络连接问题排查 |
| Handle | 句柄查看和管理 | 句柄泄漏诊断 |
| DiskMon | 磁盘活动监控 | 磁盘 I/O 问题分析 |
第三方专业工具
| 工具名称 | 类型 | 主要功能 | 适用场景 | 优势 | 局限 |
|---|---|---|---|---|---|
| Intel VTune Profiler | CPU/GPU 分析 | CPU 性能分析、热点分析、内存带宽分析 | Intel 平台深度性能分析 | 功能强大、支持硬件事件采样 | 商业软件、主要针对 Intel 平台 |
| AMD uProf | CPU/GPU 分析 | AMD 平台性能分析、硬件计数器分析 | AMD 平台性能优化 | 针对 AMD 平台优化、免费 | 仅支持 AMD 平台 |
| NVIDIA Nsight | GPU 分析 | GPU 性能分析、CUDA 调试 | GPU 应用性能优化 | GPU 分析功能强大 | 主要针对 NVIDIA GPU |
| JetBrains dotMemory | 内存分析 | .NET 内存分析、内存泄漏检测 | .NET 应用内存问题诊断 | 界面友好、分析深入 | 商业软件、主要针对 .NET |
| Very Sleepy | CPU 采样分析 | 轻量级 CPU 采样分析器 | 快速 CPU 热点定位 | 免费、轻量、易用 | 功能相对简单 |
| CodeXL | GPU 分析 | AMD GPU 性能分析工具 | AMD GPU 应用优化 | 免费、功能全面 | 已停止更新,被 uProf 替代 |
内存检测工具
| 工具名称 | 类型 | 主要功能 | 适用场景 |
|---|---|---|---|
| AddressSanitizer (ASan) | 编译时插桩 | 多种内存错误检测 | 开发阶段内存错误检测 |
| Dr. Memory | 运行时插桩 | 内存错误检测、内存泄漏检测 | 无需重新编译的内存检测 |
| UMDH | 堆分析 | 堆内存泄漏检测 | Windows 堆内存泄漏分析 |
| CRTDBG | 运行时检测 | malloc 内存泄漏检测 | C 运行时内存泄漏检测 |
| tcmalloc | 内存分配器 | 高性能内存分配、内存分析 | 内存分配性能优化 |
企业级监控工具
| 工具名称 | 类型 | 主要功能 | 适用场景 |
|---|---|---|---|
| System Center Operations Manager (SCOM) | 企业监控 | 服务器、应用、服务监控 | 企业级基础设施监控 |
| SolarWinds Server & Application Monitor | 应用监控 | 服务器和应用性能监控 | 企业应用性能监控 |
| Datadog | 云监控 | 跨平台监控、APM、日志分析 | 云环境和混合环境监控 |
| New Relic | APM | 应用性能监控、错误追踪 | 应用性能监控和分析 |
硬件监测工具
| 工具名称 | 主要功能 | 适用场景 |
|---|---|---|
| HWiNFO | 硬件传感器监控(温度、电压、风扇、GPU) | 硬件健康状态监测 |
| CPU-Z | CPU 和系统信息查看 | 硬件信息查询 |
| GPU-Z | GPU 信息查看 | GPU 信息查询 |
| Core Temp | CPU 温度监控 | CPU 温度实时监控 |
基准测试工具
| 工具名称 | 主要功能 | 适用场景 |
|---|---|---|
| DiskSpd | 存储设备 I/O 基准测试 | 磁盘性能测试 |
| CrystalDiskMark | 磁盘性能测试 | 磁盘读写速度测试 |
| 3DMark | GPU 性能基准测试 | GPU 性能测试 |
| Cinebench | CPU 渲染性能测试 | CPU 性能测试 |
二、内存工具
概述
内存问题是 Windows 应用开发中最常见的性能问题之一。本章节介绍各种内存检测和分析工具,帮助开发者快速定位内存泄漏、内存错误等问题。
工具对比:
| 工具 | 检测类型 | 性能开销 | 侵入性 | 适用场景 |
|---|---|---|---|---|
| tcmalloc | 内存分配性能 | 低 | 中等(需链接库) | 内存分配性能优化 |
| UMDH | 堆内存泄漏 | 低 | 低(运行时) | Windows 堆内存泄漏分析 |
| CRTDBG | malloc 泄漏 | 低 | 低(运行时) | C 运行时内存泄漏检测 |
| AddressSanitizer | 多种内存错误 | 高(2-3倍) | 低(编译时启用) | 开发阶段内存错误检测 |
| Dr. Memory | 多种内存错误 | 中等(5-10倍) | 无(二进制插桩) | 无需重新编译的内存检测 |
2.1 tcmalloc
概述
tcmalloc(Thread-Caching Malloc)是 Google 开发的高性能内存分配器,相比标准 malloc 具有更好的多线程性能和更低的内存碎片。
特点:
– ✅ 高性能内存分配
– ✅ 低内存碎片
– ✅ 内置内存分析功能
– ✅ 支持堆分析工具
使用
1. 下载和编译
- 下载 gperftools
- 打开
gperftools.sln编译libtcmalloc_minimal - 修改引入工程属性:
- 附加依赖项输入:
libtcmalloc_minimal.lib - 强制符号引用添加:
__tcmalloc

2. 使用堆分析工具(可选)
tcmalloc 内置了堆分析工具,可以通过环境变量启用:
set HEAPPROFILE=heap_profile
set HEAPCHECK=normal
源码分析
调用流程:
malloc -> Perftools_malloc(path_function.cc)
注意事项
- 需要链接 tcmalloc 库,会增加二进制文件大小
- 某些第三方库可能与 tcmalloc 不兼容
- 建议在性能关键的应用中使用
2.2 UMDH
概述
UMDH(User-Mode Dump Heap)是 Windows SDK 提供的堆内存分析工具,用于检测堆内存泄漏。它通过对比不同时间点的堆快照来找出内存泄漏。
特点:
– ✅ 无需重新编译程序
– ✅ 低性能开销
– ✅ 可以检测 malloc、heap_alloc 内存分配请求
– ❌ alloc-free 配对的内存不会体现在内存快照中
– ❌ 无法检测 VirtualAlloc 内存泄漏
可以检测的内存类型
- ✅ 可以检测
malloc、heap_alloc内存分配请求 - ❌
alloc-free配对的内存不会体现在内存快照中 - ❌ 无法检测
VirtualAlloc内存泄漏
使用步骤
1. 环境配置
设置 UMDH 环境变量:
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86
注意:若要确保准确的结果,必须禁用 BSTR 缓存。为此,请将
OANOCACHE环境变量设置为等于 1(在启动要跟踪其分配的应用程序之前,请进行此设置)。
2. 开启用户态 heap check
使用 gflags 开启用户态 heap check:


3. 注入测试程序
set OANOCACHE=1
gflags.exe /i wemeetapp.exe +ust
// 取消设置
gflags.exe /i wemeetapp.exe -ust
4. 创建 heap 快照
启动测试程序(wemeetapp.exe),会议当前在大厅:
umdh -p:[pid] -f:home.log
会议进房,并开启音视频,运行一段时间后:
umdh -p:[pid] -f:room.log
5. 对比两个快照的 heap 差异
umdh -d home.log room.log -f:diff.txt
结果分析
对比文件会显示:
– 内存增长:显示哪些调用栈分配了更多内存
– 调用栈信息:显示内存分配的调用栈,帮助定位泄漏位置
– 内存大小:显示泄漏的内存大小
示例输出:
+ 1000000 ( 1000000 - 0) 1 allocs BackTrace00
+ + 1 ( 1 - 0) BackTrace00 allocations
ntdll!RtlDebugAllocateHeap+0x0000000000000030
ntdll!RtlAllocateHeap+0x0000000000000076
msvcr120!malloc+0x0000000000000019
MyApp!LeakFunction+0x0000000000000010
最佳实践
- 选择合适的快照时机:
- 第一个快照:程序启动后、执行关键操作前
-
第二个快照:执行关键操作后、运行一段时间
-
多次对比:
- 可以创建多个快照,对比不同阶段的堆变化
-
有助于识别渐进式内存泄漏
-
结合其他工具:
- 与 Process Explorer 结合使用,查看进程内存趋势
-
与 WinDbg 结合使用,深入分析内存问题
-
注意事项:
- 确保程序在两次快照之间执行了可能泄漏的操作
- 避免在程序退出时创建快照(可能显示所有未释放的内存)
2.3 CRTDBG 内存泄漏检测
概述
CRTDBG 是 Visual C++ 运行时库提供的内存泄漏检测功能,可以在程序退出时检测未释放的内存。
特点:
– ✅ Windows 自带,无需额外工具
– ✅ 简单易用
– ✅ 可以显示泄漏内存的调用栈
– ❌ 只能检测 malloc 函数的内存泄漏,无法检测 heap_alloc
– ❌ 需要在程序退出时调用
使用方法
1. 基本使用
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
int main(int argc, char** argv)
{
// 启用内存泄漏检测
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
char *str = (char*)malloc(20 * sizeof(char));
// 在程序退出前输出内存泄漏信息
_CrtDumpMemoryLeaks();
return 0;
}
2. 输出到文件
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3. 设置断点
当检测到内存泄漏时,可以在特定分配处设置断点:
// 在调试器中,当分配编号为 123 的内存时中断
_CrtSetBreakAlloc(123);
注意事项
- 需要在 Debug 模式下编译才能获得完整的调用栈信息
- 某些第三方库可能产生误报
- 适合开发阶段使用,不适合生产环境
2.4 句柄泄露检测
使用 WinDbg 命令检测句柄泄露:
!htrace -enable
!htrace -diff
!handle [句柄]
使用步骤:
- 在 WinDbg 中附加到目标进程
- 执行
!htrace -enable启用句柄追踪 - 执行需要检测的操作
- 执行
!htrace -diff查看句柄变化 - 使用
!handle [句柄值]查看具体句柄信息
2.5 AddressSanitizer (ASan)
概述
AddressSanitizer(ASan)是一种运行时内存错误检测器,用于捕获诸如越界访问(out-of-bounds)、使用已释放内存(use-after-free)、栈溢出、堆溢出、内存泄漏等问题。最初由 LLVM/Clang 实现,现在 Windows 上的 MSVC 和 Clang-CL 都提供了支持。
支持情况
| 工具/编译器 | 支持情况 |
|---|---|
| MSVC (cl.exe) | Visual Studio 2019 16.9 起提供支持 |
| Clang/Clang-CL | 完整支持 ASan |
| 架构支持 | x86、x64(ARM64 在 VS 2026 中支持,预览版) |
使用步骤
1. 环境要求
- Visual Studio 2019 16.9 或更高版本
- 确保安装了 C++ 工作负载(Desktop development with C++)
2. MSVC 编译器启用 ASan
在项目属性中配置:
- C/C++ → 常规 → 启用 AddressSanitizer:选择”是 (/fsanitize=address)”
- 或者直接在命令行添加:
/fsanitize=address
示例项目配置:
项目属性 → C/C++ → 常规
启用 AddressSanitizer: 是 (/fsanitize=address)
3. Clang-CL 编译器启用 ASan
使用 Clang-CL 时,添加编译选项:
clang-cl -fsanitize=address main.cpp -o main.exe
4. 环境变量配置(可选)
可以通过 ASAN_OPTIONS 环境变量调整 ASan 行为:
set ASAN_OPTIONS=windows_hook_rtl_allocators=true
常用选项:
– windows_hook_rtl_allocators=true:启用对 Windows RTL 分配器的钩挂
– detect_leaks=1:启用内存泄漏检测
– abort_on_error=1:检测到错误时立即终止程序
5. 运行和调试
- 在 Visual Studio 中运行启用了 ASan 的程序时,调试器会自动捕获内存错误
- 错误信息会显示在输出窗口,包括错误类型、内存地址、调用堆栈等
- ASan 会在检测到错误时自动中断程序执行
示例输出:
=================================================================
==12345==ERROR: AddressSanitizer: heap-use-after-free on address 0x...
#0 0x7ff... in main main.cpp:10
#1 0x7ff... in __scrt_common_main_seh
检测的内存错误类型
- ✅ 堆缓冲区溢出:访问堆分配的内存边界之外
- ✅ 栈缓冲区溢出:访问栈分配的内存边界之外
- ✅ 使用已释放内存:访问已经被 free/delete 的内存
- ✅ 使用作用域外内存:访问超出作用域的栈变量
- ✅ 内存泄漏:分配的内存未释放(需要启用
detect_leaks) - ✅ 双重释放:对同一块内存释放两次
限制与注意事项
- 性能开销:
- 编译速度变慢
- 运行时内存开销显著增加(shadow memory、额外的运行时检查)
-
通常会使程序运行速度降低 2-3 倍
-
库兼容性:
- 所有被引用的库最好也用 ASan 构建
-
混合使用(一些库不带 ASan)可能导致某些错误检测失效或误报
-
调试符号:
-
建议在 Debug 模式下使用,确保有完整的调试符号信息
-
版本兼容性:
- 早期版本可能存在兼容性问题
- 建议使用 Visual Studio 2019 16.9 或更高版本
与其他工具对比
| 工具 | 检测类型 | 性能开销 | 侵入性 |
|---|---|---|---|
| AddressSanitizer | 多种内存错误 | 高(2-3倍) | 低(编译时启用) |
| UMDH | 堆内存泄漏 | 低 | 低(运行时) |
| CRTDBG | malloc 泄漏 | 低 | 低(运行时) |
| Dr. Memory | 多种内存错误 | 中等 | 无(二进制插桩) |
2.6 Dr. Memory
概述
Dr. Memory 是一个内存错误检测工具,类似于 Linux 上的 Valgrind,但专门为 Windows 平台设计。它使用动态二进制插桩(Dynamic Binary Instrumentation)技术,可以在不重新编译程序的情况下检测内存错误。
特点:
– ✅ 无需重新编译程序(二进制插桩)
– ✅ 支持检测多种内存错误类型
– ✅ 支持 32 位和 64 位应用程序
– ✅ 开源免费工具
检测的内存错误类型
- ✅ 未初始化内存访问:使用未初始化的变量
- ✅ 内存泄漏:分配的内存未释放
- ✅ 使用已释放内存:访问已经被 free/delete 的内存
- ✅ 堆缓冲区溢出:访问堆分配的内存边界之外
- ✅ 栈缓冲区溢出:访问栈分配的内存边界之外
- ✅ GDI 句柄泄漏:Windows GDI 对象泄漏
- ✅ 句柄泄漏:Windows 句柄泄漏
下载和安装
1. 下载
从官方网站下载:https://github.com/DynamoRIO/drmemory/releases
或者使用预编译版本:
– 32 位版本:DrMemory-Windows-2.x.x-32.exe
– 64 位版本:DrMemory-Windows-2.x.x-64.exe
2. 安装
解压到任意目录,例如:C:\DrMemory
3. 配置环境变量(可选)
将 Dr. Memory 的 bin 目录添加到 PATH 环境变量中,方便命令行使用。
使用方法
1. 基本用法
drmemory.exe [选项] 程序名 [程序参数]
示例:
# 检测内存错误
drmemory.exe -- your_program.exe arg1 arg2
# 检测内存泄漏
drmemory.exe -leaks_only -- your_program.exe
# 检测未初始化内存
drmemory.exe -check_uninitialized -- your_program.exe
2. 常用选项
| 选项 | 说明 |
|---|---|
-leaks_only |
仅检测内存泄漏,不检测其他错误 |
-check_uninitialized |
检测未初始化内存访问 |
-suppress |
使用抑制文件忽略已知的误报 |
-logdir |
指定日志输出目录 |
-brief |
简要输出模式 |
-count |
仅统计错误数量,不输出详细信息 |
-quiet |
静默模式,减少输出 |
3. 输出结果分析
Dr. Memory 会在程序运行结束后输出详细的错误报告,包括:
- 错误类型:如 “UNADDRESSABLE ACCESS”、”UNINITIALIZED READ”、”LEAK” 等
- 错误位置:调用堆栈信息
- 内存地址:发生错误的内存地址
- 错误大小:访问的内存大小
示例输出:
Error #1: UNADDRESSABLE ACCESS
# 0 replace_malloc [d:\drmemory_package\common\alloc_replace.c:2576]
# 1 test_leak [test.cpp:15]
# 2 main [test.cpp:25]
Error #2: LEAK 20 bytes
# 0 replace_malloc [d:\drmemory_package\common\alloc_replace.c:2576]
# 1 test_leak [test.cpp:15]
# 2 main [test.cpp:25]
4. 抑制误报
对于已知的误报(如第三方库的问题),可以创建抑制文件:
创建抑制文件 suppress.txt:
# 抑制某个 DLL 的所有错误
suppress_lib "third_party.dll"
# 抑制特定函数的错误
suppress_func "some_function"
使用抑制文件:
drmemory.exe -suppress suppress.txt -- your_program.exe
与其他工具对比
| 特性 | Dr. Memory | AddressSanitizer | UMDH |
|---|---|---|---|
| 需要重新编译 | ❌ 否 | ✅ 是 | ❌ 否 |
| 检测未初始化内存 | ✅ | ✅ | ❌ |
| 检测内存泄漏 | ✅ | ✅(需配置) | ✅ |
| 检测缓冲区溢出 | ✅ | ✅ | ❌ |
| 性能开销 | 中等(5-10倍) | 高(2-3倍) | 低 |
| 支持 64 位 | ✅ | ✅ | ✅ |
限制与注意事项
- 性能开销:
- 程序运行速度会显著降低(通常 5-10 倍)
-
内存占用会增加
-
兼容性:
- 某些使用特殊技术的程序可能无法正常运行
-
不支持 .NET 应用程序(仅支持原生 C/C++ 程序)
-
误报:
- 某些第三方库可能产生误报
-
需要使用抑制文件过滤
-
调试符号:
- 建议使用 Debug 版本的程序,以便获得更准确的堆栈信息
-
确保 PDB 文件可用
-
64 位支持:
- 64 位版本在某些情况下可能不如 32 位版本稳定
最佳实践
- 开发阶段使用:在开发和测试阶段使用 Dr. Memory 检测内存错误
- CI/CD 集成:可以在持续集成流程中运行 Dr. Memory 进行自动化检测
- 定期检查:定期对关键模块进行内存检查
- 结合其他工具:与 AddressSanitizer、UMDH 等工具结合使用,互相补充
- 抑制文件管理:维护抑制文件,记录已知的误报和第三方库问题
示例:检测内存泄漏
测试程序 test_leak.cpp:
#include <iostream>
#include <cstdlib>
void test_leak() {
char* ptr = (char*)malloc(100);
// 忘记释放内存
// free(ptr);
}
int main() {
test_leak();
std::cout << "Test completed" << std::endl;
return 0;
}
编译和检测:
# 编译程序
cl /Zi test_leak.cpp /Fe:test_leak.exe
# 使用 Dr. Memory 检测
drmemory.exe -leaks_only -- test_leak.exe
输出结果:
Dr. Memory version 2.x.x
...
Error #1: LEAK 100 bytes
# 0 replace_malloc [alloc_replace.c:2576]
# 1 test_leak [test_leak.cpp:5]
# 2 main [test_leak.cpp:11]
NO ERRORS FOUND for unaddressable access(es)
NO ERRORS FOUND for uninitialized access(es)
1 unique error(s) found
三、CPU 工具
概述
CPU 性能分析是性能优化的核心环节。本章节介绍各种 CPU 分析工具,帮助开发者定位 CPU 热点、线程调度问题等。
工具对比:
| 工具 | 类型 | 平台支持 | 硬件事件 | 适用场景 |
|---|---|---|---|---|
| WPT | 系统级分析 | Windows | ✅ | 系统级性能问题、驱动问题 |
| Very Sleepy | 采样分析 | Windows | ❌ | 快速 CPU 热点定位 |
| AMD uProf | 硬件分析 | AMD 平台 | ✅ | AMD 平台性能优化 |
| Intel VTune | 硬件分析 | Intel 平台 | ✅ | Intel 平台深度性能分析 |
3.1 WPT (Windows Performance Toolkit)
概述
WPT(Windows Performance Toolkit)是 Windows 官方提供的系统级性能分析工具集,包含 WPR(Windows Performance Recorder)和 WPA(Windows Performance Analyzer)。它基于 ETW(Event Tracing for Windows)技术,可以追踪系统级和应用级的性能事件。
主要组件:
– WPR:性能数据录制工具,通过配置文件指定启动的 provider、session 及其他参数
– WPA:性能数据分析工具,提供强大的数据可视化和分析功能
特点:
– ✅ 系统级性能分析
– ✅ 支持驱动和硬件事件追踪
– ✅ 支持自定义 ETW Provider
– ✅ 强大的数据可视化
– ❌ 学习曲线陡峭
– ❌ 数据量大,资源消耗高
WPA 使用说明
- 金色条:左边的列都会合并为树状展示,并作为图的系列
- 蓝色条:右侧的列作为图的数据
- 数据表:是透视表。垂直金色条左侧的列是键。垂直金色条和垂直蓝色条之间的列是数据列。如果没有看到垂直金色条,请向右滚动
环境变量配置
NT_SOURCE_PATH:源文件目录
_NT_SYMBOL_PATH:PDB 目录
_NT_SYMCACHE_PATH:PDB 缓存目录
UI Delay 检测
从 Windows 7 开始,内核中新加了一种 ETW 提供者,当应用程序超过 200 毫秒不检测其消息队列时,它会产生一个事件。UI for ETW 默认启用该 ETW 提供者,我们可以在 WPA 的 System Activity 窗口的 UI Delay 图表中看到这些事件。
常用命令
REM 开始采集
wpr.exe -start CPU -filemode
REM 结束采集
wpr.exe -stop "34.txt"
REM 放弃本次采集
wpr.exe -cancel
REM 导出 CSV(wpaProfile 从 wpa 导出)
wpaexporter.exe -i {etl_file} -profile cpuusage.wpaProfile -outputfolder {output_dir} -symbols
常见问题
3.1.1 打开分析文件错误
错误码:0x80070032


原因:This is usually caused by insufficient disk bandwidth for ETW logging
解决方案:
– 使用 SSD 存储 ETL 文件
– 减少缓冲区大小和数量
– 使用内存模式(Memory)而不是文件模式(File)
3.1.2 SDK 版本不匹配
注意:SDK 安装默认使用最新的版本,可能和安装系统不一定匹配,会出现比如
wprui.exe无法打开的情况,最好手工选择合适版本。
解决方案:
– 安装与系统版本匹配的 Windows SDK
– 使用命令行工具 wpr.exe 代替 GUI 工具
最佳实践
- 选择合适的 Profile:
- Light:快速分析,数据量小
- Verbose:详细分析,数据量大
-
自定义 Profile:针对特定场景优化
-
优化缓冲区配置:
- 内存模式:适合短期分析
- 文件模式:适合长期分析
-
调整缓冲区大小和数量以平衡性能和资源占用
-
符号文件配置:
- 确保配置了正确的符号路径
- 使用符号服务器自动下载符号
-
缓存符号文件以提高分析速度
-
分析技巧:
- 使用 WPA 的筛选功能缩小分析范围
- 关注 CPU 使用率高的时间段
- 结合调用栈信息定位问题
3.2 Very Sleepy
概述
Very Sleepy 是一个轻量级、免费的 CPU 采样分析器,适用于 Windows 平台。它通过采样方式收集程序的 CPU 使用情况,帮助开发者快速定位性能热点。
特点:
– ✅ 免费开源
– ✅ 轻量级,无需安装
– ✅ 无需重新编译程序
– ✅ 界面简洁易用
使用方法
1. 下载
从 GitHub 下载:https://github.com/VerySleepy/verysleepy/releases
2. 基本使用
- 启动 Very Sleepy
- 点击 “Profile” 按钮
- 选择要分析的程序(或输入进程 ID)
- 点击 “Start” 开始采样
- 运行程序执行需要分析的操作
- 点击 “Stop” 停止采样
- 查看结果:按函数调用次数或时间排序,定位热点函数
3. 结果分析
- 函数列表:显示每个函数的调用次数和占用时间
- 调用树:显示函数调用关系
- 源代码视图:如果有符号文件,可以查看源代码行级别的性能数据
4. 注意事项
- 采样频率会影响结果准确性(默认 1000Hz)
- 需要调试符号(PDB 文件)才能看到函数名和源代码信息
- 采样型分析器可能漏掉短时间执行的函数
- 适合快速定位 CPU 热点,不适合分析内存问题
适用场景
- 快速定位 CPU 性能瓶颈
- 开发阶段的性能初步分析
- 不需要深度系统级分析的场景
3.3 AMD uProf
概述
AMD uProf(AMD Unified Profiler)是 AMD 官方提供的性能分析工具,支持 CPU 和 GPU 性能分析。它是 CodeXL 的替代工具,提供更现代化的界面和更好的硬件支持。
特点:
– ✅ AMD 官方维护的工具
– ✅ 支持 AMD CPU 和 Radeon GPU 性能分析
– ✅ 支持硬件事件采样
– ✅ 免费使用
– ✅ 现代化的图形界面
主要功能
- CPU 性能分析:
- 硬件事件采样(缓存未命中、分支预测失败等)
- CPU 热点分析
- 线程和核心利用率分析
-
功耗分析
-
GPU 性能分析:
- Radeon GPU 性能分析
- GPU 内核分析
- GPU 时间线视图
-
GPU 功耗分析
-
系统级监控:
- 系统资源使用情况
- 多进程性能分析
- 性能计数器监控
下载和安装
下载地址:https://www.amd.com/en/developer/uprof.html
系统要求:
– Windows 10/11(64 位)
– AMD CPU 或 AMD Radeon GPU
– 管理员权限(某些功能需要)
使用方法
1. 基本使用流程
- 启动 AMD uProf
- 选择分析类型(CPU 或 GPU)
- 选择要分析的程序或进程
- 配置分析选项(采样频率、事件类型等)
- 点击 “Start” 开始分析
- 运行程序执行需要分析的操作
- 点击 “Stop” 停止分析
- 查看分析结果
2. CPU 性能分析
- 硬件事件采样:选择要监控的硬件事件(如 L1/L2/L3 缓存未命中、分支预测失败等)
- 热点分析:查看函数和源代码行的 CPU 使用情况
- 线程分析:分析线程调度和核心利用率
3. GPU 性能分析
- GPU 内核分析:分析 GPU 内核的执行时间和占用率
- API 追踪:追踪 DirectX、OpenCL、Vulkan 等 API 调用
- 时间线视图:查看 GPU 活动的时序图
4. 结果分析
- 函数列表:按 CPU 时间或调用次数排序
- 调用树:显示函数调用关系
- 源代码视图:查看源代码行级别的性能数据
- 图表视图:可视化性能数据
适用场景
- AMD 平台的性能优化
- CPU 硬件事件分析
- GPU 应用性能分析
- 功耗分析
- 多线程性能分析
注意事项
- 主要针对 AMD 硬件优化,Intel 平台支持有限
- 需要调试符号(PDB 文件)才能看到函数名和源代码信息
- 某些功能需要管理员权限
- GPU 分析需要 AMD Radeon GPU
与其他工具对比
| 工具 | CPU 分析 | GPU 分析 | 硬件事件 | 平台支持 |
|---|---|---|---|---|
| AMD uProf | ✅ | ✅(AMD GPU) | ✅ | AMD 平台 |
| Intel VTune | ✅ | ✅(Intel GPU) | ✅ | Intel 平台 |
| NVIDIA Nsight | ❌ | ✅(NVIDIA GPU) | ❌ | NVIDIA GPU |
| Very Sleepy | ✅ | ❌ | ❌ | 通用 |
3.4 Windows 性能打点
生成 Manifest 文件
使用工具:C:\Program Files (x86)\Windows Kits\8.1\bin\x64\ecmangen.exe
编译 Manifest 文件
"C:\Program Files (x86)\Windows Kits\8.1\bin\x64\mc.exe" -um etwproviders.man -z etwproviders
系统注册 Providers
注意:需要管理员权限运行
wevtutil im signpost_win.man /rf:绝对路径\wemeet_base.dll /mf:绝对路径\wemeet_base.dll
REM 示例
wevtutil im signpost_win.man /rf:"C:\Program Files (x86)\Tencent\WeMeet Dev\3.20.0.35859\wemeet_base.dll" /mf:"C:\Program Files (x86)\Tencent\WeMeet Dev\3.20.0.35859\wemeet_base.dll"
REM 注册表位置
REM 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\{9b00a176-e17a-4777-99c3-8b51cc33895a}
REM 卸载
wevtutil um signpost_win.man
WPRUI 录制配置
录制时选择自定义 wprp
启动 WPR,选择添加 add profiles,添加如下 profiles,并启动录制:

WPR Profile 配置示例:
<?xml version="1.0" encoding="utf-8"?>
<WindowsPerformanceRecorder Version="1.0" Author="WPT team">
<Profiles>
<EventCollector Id="EventCollector_WPR" Name="SimpleEventLogger">
<BufferSize Value="256"/> <!-- Optional. Default value is 128-->
<Buffers Value="64"/> <!-- Optional. Default value is 64 -->
</EventCollector>
<EventProvider Id="EventProvider_WPR_Status" Name="Wemeet Signpost Provider">
<Keywords> <!-- Optional. Default value is 0xFFFFFFFFFFFFFFFF -->
<Keyword Value="0x40000"/>
</Keywords>
</EventProvider>
<Profile Id="WPRTest2.Light.File" LoggingMode="File" Name="WPRTest2" DetailLevel="Light" Description="WPR Test2">
<Collectors>
<EventCollectorId Value="EventCollector_WPR">
<EventProviders>
<EventProviderId Value="EventProvider_WPR_Status"/>
</EventProviders>
</EventCollectorId>
</Collectors>
</Profile>
<!-- Optional other flavors of the profile-->
<Profile Id="WPRTest2.Light.Memory" Base="WPRTest2.Light.File" LoggingMode="Memory" Name="WPRTest2" DetailLevel="Light" Description="WPR Test2"/>
<Profile Id="WPRTest2.Verbose.File" Base="WPRTest2.Light.File" LoggingMode="File" Name="WPRTest2" DetailLevel="Verbose" Description="WPR Test2"/>
<Profile Id="WPRTest2.Verbose.Memory" Base="WPRTest2.Light.File" LoggingMode="Memory" Name="WPRTest2" DetailLevel="Verbose" Description="WPR Test2"/>
</Profiles>
</WindowsPerformanceRecorder>
3.5 采集堆栈格式
格式说明:模块路径|pdb名称 模块基地址 调用地址 模块时间戳 模块签名
示例:
[
"C:/Program Files (x86)/Tencent/WeMeet/3.19.0.1/wemeet_plugins.dll|wemeet_plugins.pdb 65260000 6538810f 64cc7ca8 3FAC3B17FECF4CB9AD0B06FC51D0D5C01",
"C:/Program Files (x86)/Tencent/WeMeet/3.19.0.1/wemeet_plugins.dll|wemeet_plugins.pdb 65260000 65387086 64cc7ca8 3FAC3B17FECF4CB9AD0B06FC51D0D5C01",
"C:/Program Files (x86)/Tencent/WeMeet/3.19.0.1/wemeet_plugins.dll|wemeet_plugins.pdb 65260000 65385aeb 64cc7ca8 3FAC3B17FECF4CB9AD0B06FC51D0D5C01",
"C:/Program Files (x86)/Tencent/WeMeet/3.19.0.1/wemeet_plugins.dll|wemeet_plugins.pdb 65260000 653874ad 64cc7ca8 3FAC3B17FECF4CB9AD0B06FC51D0D5C01"
]
四、符号还原
概述
符号文件(PDB)是调试和性能分析的关键。本章节介绍如何下载、管理和使用符号文件,以便在性能分析时获得准确的函数名和源代码信息。
4.1 符号下载
符号路径格式
拼接下载 URL,格式为:url + pdb.name + guid
示例路径:
E:\symbols\acpi.pdb\4C0A23D5AC858EAA089DEE6EB946A4FA1\acpi.pdb
命令行自动下载符号
symchk /v C:\WINDOWS\SYSTEM32\MSVCP140D.dll
填入用户名称和密码即可自动下载。
4.2 Dia2Dump
Dia2Dump 是 Windows SDK 提供的工具,用于从 PDB 文件中提取符号信息。
RVA 查询符号
Dia2Dump.exe -sym "1b2d4" IDbgCppunit.exe
RVA 查询行号
Dia2Dump.exe -lines 1b2d4 IDbgCppunit.exe
函数符号查询地址
Dia2Dump.exe -sym "ShowGood" IDbg.dll
4.3 WinDbg 符号命令
agestore – 管理符号表
agestore c:\symbols\downstreamstore -days=30 -s
参数说明:
– -days=30:保留 30 天内的符号文件
– -s:递归处理子目录
符号路径相关命令
REM 查看符号路径
.sympath
REM 设置符号路径为微软符号服务器
.symfix
REM 添加自定义符号路径
.sympath+ C:\MySymbols
