Windows 性能工具

Windows 性能工具

目录

一、概览

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. 下载和编译

  1. 下载 gperftools
  2. 打开 gperftools.sln 编译 libtcmalloc_minimal
  3. 修改引入工程属性:
  4. 附加依赖项输入:libtcmalloc_minimal.lib
  5. 强制符号引用添加:__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 提供的堆内存分析工具,用于检测堆内存泄漏。它通过对比不同时间点的堆快照来找出内存泄漏。

特点
– ✅ 无需重新编译程序
– ✅ 低性能开销
– ✅ 可以检测 mallocheap_alloc 内存分配请求
– ❌ alloc-free 配对的内存不会体现在内存快照中
– ❌ 无法检测 VirtualAlloc 内存泄漏

可以检测的内存类型

  • ✅ 可以检测 mallocheap_alloc 内存分配请求
  • alloc-free 配对的内存不会体现在内存快照中
  • ❌ 无法检测 VirtualAlloc 内存泄漏

使用步骤

1. 环境配置

设置 UMDH 环境变量:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x86

注意:若要确保准确的结果,必须禁用 BSTR 缓存。为此,请将 OANOCACHE 环境变量设置为等于 1(在启动要跟踪其分配的应用程序之前,请进行此设置)。

2. 开启用户态 heap check

使用 gflags 开启用户态 heap check:

gflags 配置

gflags 设置

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

最佳实践

  1. 选择合适的快照时机
  2. 第一个快照:程序启动后、执行关键操作前
  3. 第二个快照:执行关键操作后、运行一段时间

  4. 多次对比

  5. 可以创建多个快照,对比不同阶段的堆变化
  6. 有助于识别渐进式内存泄漏

  7. 结合其他工具

  8. 与 Process Explorer 结合使用,查看进程内存趋势
  9. 与 WinDbg 结合使用,深入分析内存问题

  10. 注意事项

  11. 确保程序在两次快照之间执行了可能泄漏的操作
  12. 避免在程序退出时创建快照(可能显示所有未释放的内存)

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 [句柄]

使用步骤

  1. 在 WinDbg 中附加到目标进程
  2. 执行 !htrace -enable 启用句柄追踪
  3. 执行需要检测的操作
  4. 执行 !htrace -diff 查看句柄变化
  5. 使用 !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
  • 双重释放:对同一块内存释放两次

限制与注意事项

  1. 性能开销
  2. 编译速度变慢
  3. 运行时内存开销显著增加(shadow memory、额外的运行时检查)
  4. 通常会使程序运行速度降低 2-3 倍

  5. 库兼容性

  6. 所有被引用的库最好也用 ASan 构建
  7. 混合使用(一些库不带 ASan)可能导致某些错误检测失效或误报

  8. 调试符号

  9. 建议在 Debug 模式下使用,确保有完整的调试符号信息

  10. 版本兼容性

  11. 早期版本可能存在兼容性问题
  12. 建议使用 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 位

限制与注意事项

  1. 性能开销
  2. 程序运行速度会显著降低(通常 5-10 倍)
  3. 内存占用会增加

  4. 兼容性

  5. 某些使用特殊技术的程序可能无法正常运行
  6. 不支持 .NET 应用程序(仅支持原生 C/C++ 程序)

  7. 误报

  8. 某些第三方库可能产生误报
  9. 需要使用抑制文件过滤

  10. 调试符号

  11. 建议使用 Debug 版本的程序,以便获得更准确的堆栈信息
  12. 确保 PDB 文件可用

  13. 64 位支持

  14. 64 位版本在某些情况下可能不如 32 位版本稳定

最佳实践

  1. 开发阶段使用:在开发和测试阶段使用 Dr. Memory 检测内存错误
  2. CI/CD 集成:可以在持续集成流程中运行 Dr. Memory 进行自动化检测
  3. 定期检查:定期对关键模块进行内存检查
  4. 结合其他工具:与 AddressSanitizer、UMDH 等工具结合使用,互相补充
  5. 抑制文件管理:维护抑制文件,记录已知的误报和第三方库问题

示例:检测内存泄漏

测试程序 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 工具

最佳实践

  1. 选择合适的 Profile
  2. Light:快速分析,数据量小
  3. Verbose:详细分析,数据量大
  4. 自定义 Profile:针对特定场景优化

  5. 优化缓冲区配置

  6. 内存模式:适合短期分析
  7. 文件模式:适合长期分析
  8. 调整缓冲区大小和数量以平衡性能和资源占用

  9. 符号文件配置

  10. 确保配置了正确的符号路径
  11. 使用符号服务器自动下载符号
  12. 缓存符号文件以提高分析速度

  13. 分析技巧

  14. 使用 WPA 的筛选功能缩小分析范围
  15. 关注 CPU 使用率高的时间段
  16. 结合调用栈信息定位问题

3.2 Very Sleepy

概述

Very Sleepy 是一个轻量级、免费的 CPU 采样分析器,适用于 Windows 平台。它通过采样方式收集程序的 CPU 使用情况,帮助开发者快速定位性能热点。

特点
– ✅ 免费开源
– ✅ 轻量级,无需安装
– ✅ 无需重新编译程序
– ✅ 界面简洁易用

使用方法

1. 下载

从 GitHub 下载:https://github.com/VerySleepy/verysleepy/releases

2. 基本使用

  1. 启动 Very Sleepy
  2. 点击 “Profile” 按钮
  3. 选择要分析的程序(或输入进程 ID)
  4. 点击 “Start” 开始采样
  5. 运行程序执行需要分析的操作
  6. 点击 “Stop” 停止采样
  7. 查看结果:按函数调用次数或时间排序,定位热点函数

3. 结果分析

  • 函数列表:显示每个函数的调用次数和占用时间
  • 调用树:显示函数调用关系
  • 源代码视图:如果有符号文件,可以查看源代码行级别的性能数据

4. 注意事项

  • 采样频率会影响结果准确性(默认 1000Hz)
  • 需要调试符号(PDB 文件)才能看到函数名和源代码信息
  • 采样型分析器可能漏掉短时间执行的函数
  • 适合快速定位 CPU 热点,不适合分析内存问题

适用场景

  • 快速定位 CPU 性能瓶颈
  • 开发阶段的性能初步分析
  • 不需要深度系统级分析的场景

3.3 AMD uProf

概述

AMD uProf(AMD Unified Profiler)是 AMD 官方提供的性能分析工具,支持 CPU 和 GPU 性能分析。它是 CodeXL 的替代工具,提供更现代化的界面和更好的硬件支持。

特点
– ✅ AMD 官方维护的工具
– ✅ 支持 AMD CPU 和 Radeon GPU 性能分析
– ✅ 支持硬件事件采样
– ✅ 免费使用
– ✅ 现代化的图形界面

主要功能

  1. CPU 性能分析
  2. 硬件事件采样(缓存未命中、分支预测失败等)
  3. CPU 热点分析
  4. 线程和核心利用率分析
  5. 功耗分析

  6. GPU 性能分析

  7. Radeon GPU 性能分析
  8. GPU 内核分析
  9. GPU 时间线视图
  10. GPU 功耗分析

  11. 系统级监控

  12. 系统资源使用情况
  13. 多进程性能分析
  14. 性能计数器监控

下载和安装

下载地址:https://www.amd.com/en/developer/uprof.html

系统要求
– Windows 10/11(64 位)
– AMD CPU 或 AMD Radeon GPU
– 管理员权限(某些功能需要)

使用方法

1. 基本使用流程

  1. 启动 AMD uProf
  2. 选择分析类型(CPU 或 GPU)
  3. 选择要分析的程序或进程
  4. 配置分析选项(采样频率、事件类型等)
  5. 点击 “Start” 开始分析
  6. 运行程序执行需要分析的操作
  7. 点击 “Stop” 停止分析
  8. 查看分析结果

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 配置

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

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Index