国产化客户端软件在研发和测试过程中,通常侧重于功能实现和可用性,导致软件交互、性能及稳定性测试的覆盖度不足。软件发布后,常收到卡顿、反应迟缓和崩溃等负面反馈。为解决这一问题,并确保全面的测试覆盖,测试团队对桌面端软件性能测试工具进行了深入调研,并与研发团队一起梳理了性能场景和稳定性场景。最终整理成性能测试方案,用于指导客户端软件性能测试开展。
在 BimBase 桌面端软件典型用户操作下,量化 CPU、GPU、内存、磁盘 I/O、FileI/O 5 大资源消耗,识别性能瓶颈并建立可追踪基线,为版本迭代的性能、稳定性提升提供量化依据 。
| 模块 | 场景 | 被测对象 | 备注 |
|---|---|---|---|
| 软件启动 | 冷启动 | BimBase 主 exe 程序 | 进程生命周期→首帧可交互 |
| 文件 | 打开大文件 | XXXGB 以上单模型 | p3d、bfa、fbx、ifc、dgn 等文件耗时 |
| 建模 | 批量布置 | XX 根梁 +XX 根柱 | 参数化驱动 |
| 模型定位 | 搜索 →隔离→聚焦 | ||
| 稳定性 | 长时间运行 | XX 小时连续操作 | 监控内存泄漏、句柄泄漏等稳定性问题 |
| 交互体验 | XXM 地形、XX 个元素 | XXM 地形、XX 个元素,交互响应时间 |
被测对象
BimBase 主进程,重点监控首帧可交互时间、导入耗时、上传成功率、内存泄漏。
测试要点
本次性能测试重点关注以下内容:
%Processor Time(单位时间内进程占用处理器占比)、Context Switch(上下文切换次数,反映多线程调度开销)等,直接体现 CPU 计算压力;Private Working Set(进程私有内存占用)、Commit Size(系统承诺分配的内存总量)等,反映内存分配与泄漏风险;GPU Utilization(GPU 利用率),衡量图形计算/算力资源的消耗;File I/O Count(IO 操作次数)、I/O Duration(单次 IO 耗时)等,暴露存储子系统的读写效率。
| 序号 | 名称 | 类型 | 交付人 | 备注 |
|---|---|---|---|---|
| 1 | 测试方案 | Word | 测试组 | 含评审记录 |
| 3 | 录制 脚本文件 | WPR 图形模式 | 测试组 | 性能测试用 |
| 4 | 脚本回放文件 | 可复现的.etl 日志、图表 | ||
| 4 | 测试执行记录 | Word | 测试组 | 含关键场景执行记录 |
| 5 | 缺陷统计及分析 | ones | 测试组 | |
| 6 | 测试总结报告 | Word | 测试组 |
下载地址: https://developer.microsoft.com/zh-cn/windows/downloads/sdk-archive/
版本(与测试人员相同版本): 适用于 Windows 11 的 Windows SDK(10.0.26100.4948)

WPR(Windows Performance Recorder), Windows Performance Toolkit 的自带组件,无需另外安装。
CPU、内存、文件 I\O、磁盘 I\O 监听工具: WPA(Windows Performance Analyzer), Windows Performance Toolkit 的自带组件,无需另外安装。
NVIDIA Nsight Systems:英伟达官方插件,用于 GPU-CPU 协同的 系统级性能分析工具。
性能优化思路:多工具联动,从不同维度透视问题 。
WPA 看内核细节,Nsight 看宏观时序;两者结合可判定 GPU 空等 CPU 或反之,减少单工具盲区。
核心概念:GPU-CPU 协同工作与 “空等”
在 GPU 计算(如 CUDA)、图形渲染(如 DirectX/Vulkan)或机器学习中,一个任务通常由 CPU 和 GPU 共同完成:
1.CPU(指挥官): 负责逻辑控制、准备数据、向 GPU 发送渲染/计算命令。
2.GPU(执行者): 接收命令后,并行地进行大规模数值计算或图形渲染。
理想情况下,GPU 和 CPU 都保持忙碌,流水线无缝衔接。但现实中往往会出现一方 “空等” 另一方的情况:
GPU 空等 CPU: GPU 很快就完成了上一个任务,但迟迟等不到 CPU 下发下一个命令。这通常意味着 CPU 端存在瓶颈(例如,复杂的场景图遍历、驱动开销过大、或数据准备太慢)。
CPU 空等 GPU: CPU 很快就把命令提交给了 GPU,然后就必须停下来等待 GPU 完成计算/渲染,才能进行下一步。这通常意味着你的应用是 GPU-Bound(受 GPU 性能限制)的。
单工具盲区在于:
只用 WPA(CPU 视角): 看到的是 CPU 非常繁忙,但无法知道它提交命令后,GPU 在干什么。你可能误以为 CPU 繁忙是性能瓶颈,而实际上 GPU 才是拖后腿的那个。
只用 Nsight(GPU 视角): 看到的是 GPU 利用率很高,但无法知道在 GPU 两个任务之间的空闲间隙里,CPU 为什么没及时提交下一个任务。
下载地址: https://developer.nvidia.com/nsight-systems/get-started
解决方法:与测试使用的 WPR、WPA 版本一致。
可能原因 2:WPA 工具未安装完成。
解决方法:卸载本地 WPA 工具,重新安装。

解决方法:修改环境变量,把新版本的 WPT10 上移到 system32 上方即可解决

详细级别越高,数据量越大:当设置为Verbose(详细)级别时,会记录大量的细节信息,这会导致 ETL 文件迅速变大。
事件类型越多,数据量越大:如果启用了许多事件提供者(如文件 I/O、磁盘 I/O、CPU、内存、GPU 等),会生成大量事件数据。
缓冲区大小和数量:较大的缓冲区和较多的缓冲区数量会增加内存占用,从而导致 ETL 文件更大。
记录时间越长,数据量越大:长时间运行性能记录会积累大量数据。
减少缓冲区大小和数量,如果采用配置文件方式:将BufferSize 从2048 降低到1024,Buffers 从512 降低到256。
移除不必要的事件提供者,如在进行打开大文件测试时,只保留 CPU、FileI/O、DeskI/O、Heap usage,去掉 GPU 和其他事件。
WPT(Windows Performance Toolkit)是微软提供的一套用于分析程序性能的工具包,相对于 VS 自带的实时监听插件,WPT 支持场景录制、流量回放、可视化图表,可针对测试的原始数据进行分析(例如:排除是否其他进程干扰造成测试误判、测试机的性能本身有问题)。它其中包含两个主要的工具:
事件记录工具,使用它可以监测系统状态(CPU、磁盘 I/O、堆分配、栈调用…), 并生成一个.etl(Event trace log)日志文件。
日志分析工具,使用它可以对 WPR 生成的.etl 日志文件加以分析得出方便人阅读的数据图表。
下载对应系统 SDK→运行安装→仅勾选 Windows Performance Toolkit→一路 Next 完成;确保路径无中文。

软件安装成功后会生成 Windows Kits 文件夹,安装路径下有 wpr.exe(Windows Performance Recorder) 和 wpa.exe(Windows Performance Analyzer)。

录制与查看须用同一版本 WPT,否则.etl 无法解析;团队统一使用 10.0.26100,共享日志前确认版本号。录制只需要 4 步:启动 WPR-->录制场景配置-->录制脚本-->保存脚本。

记录参数设置:

也可以通过 Add Profiles 选项导入自定义文件,点击 Start 录制脚本,自定义文件内容比较详细,但相对生成的文件会变大。
Pttest.wprp
<WindowsPerformanceRecorder Version="1.0">
<Profiles>
<SystemCollector Id="WPR_initiated_WprApp_WPR_System_Collector" Name="WPR_initiated_WprApp_WPR System Collector">
<BufferSize Value="2048" />
<Buffers Value="512" />
</SystemCollector>
<EventCollector Id="WPR_initiated_WprApp_WPR_Event_Collector" Name="WPR_initiated_WprApp_WPR Event Collector">
<BufferSize Value="2048" />
<Buffers Value="512" />
</EventCollector>
<HeapEventCollector Id="WPR_initiated_WprApp_WPR_Internal_Heap_Collector" Name="WPR_initiated_WprApp_WPR Internal Heap Collector" Secure="true">
<BufferSize Value="2048" />
<Buffers Value="512" />
</HeapEventCollector>
<SystemProvider Id="WPR_initiated_WprApp_WPR_System_Collector_Provider">
<Keywords>
<Keyword Value="AllFaults" />
<Keyword Value="CpuConfig" />
<Keyword Value="CSwitch" />
<Keyword Value="DiskIO" />
<Keyword Value="DiskIOInit" />
<Keyword Value="DPC" />
<Keyword Value="FileIO" />
<Keyword Value="FileIOInit" />
<Keyword Value="HardFaults" />
<Keyword Value="IdealProcessor" />
<Keyword Value="Interrupt" />
<Keyword Value="Loader" />
<Keyword Value="MemoryInfo" />
<Keyword Value="MemoryInfoWS" />
<Keyword Value="Memory"/>
<Keyword Value="ProcessCounter" />
<Keyword Value="Power" />
<Keyword Value="ProcessThread" />
<Keyword Value="ReadyThread" />
<Keyword Value="SampledProfile" />
<Keyword Value="SplitIO" />
<Keyword Value="SystemCall" />
<Keyword Value="ThreadPriority" />
<Keyword Value="WDFDPC" />
<Keyword Value="WDFInterrupt" />
</Keywords>
<Stacks>
<Stack Value="CSwitch" />
<Stack Value="DiskFlushInit" />
<Stack Value="DiskReadInit" />
<Stack Value="DiskWriteInit" />
<Stack Value="FileCleanup" />
<Stack Value="FileClose" />
<Stack Value="FileCreate" />
<Stack Value="FileDelete" />
<Stack Value="FileDirEnum" />
<Stack Value="FileDirNotify" />
<Stack Value="FileFlush" />
<Stack Value="FileFSCTL" />
<Stack Value="FileOpEnd" />
<Stack Value="FileQueryInformation" />
<Stack Value="FileRead" />
<Stack Value="FileRename" />
<Stack Value="FileSetInformation" />
<Stack Value="FileWrite" />
<Stack Value="HeapAllocation" />
<Stack Value="HeapReallocation" />
<Stack Value="PagefaultHard" />
<Stack Value="SampledProfile" />
<Stack Value="ReadyThread" />
<Stack Value="ThreadDCEnd" />
</Stacks>
</SystemProvider>
<!-- ===== 追加:缺失的两个 Provider ===== -->
<EventProvider Id="KernelProcess" Name="Microsoft-Windows-Kernel-Process" Level="3" NonPagedMemory="true"/>
<EventProvider Id="KernelMemory" Name="Microsoft-Windows-Kernel-Memory" Level="3" NonPagedMemory="true"/>
<!-- 线程生命周期,用于 File I/O 等视图的 Thread Name -->
<EventProvider Id="KernelThread" Name="Microsoft-Windows-Kernel-Thread" Level="3" NonPagedMemory="true"/>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_b675ec37-bdb6-4648-bc92-f3fdc74d3ca2" Name="b675ec37-bdb6-4648-bc92-f3fdc74d3ca2" NonPagedMemory="true" Level="3">
<Keywords>
<Keyword Value="0x0000000000000040" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_57277741-3638-4a4b-bdba-0ac6e45da56c" Name="57277741-3638-4a4b-bdba-0ac6e45da56c" NonPagedMemory="true" Stack="true">
<Keywords>
<Keyword Value="0x0000000000400001" />
</Keywords>
<CaptureStateOnSave Timeout="30">
<Keyword Value="0x0000000000000004" />
</CaptureStateOnSave>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_36b6f488-aad7-48c2-afe3-d4ec2c8b46fa" Name="36b6f488-aad7-48c2-afe3-d4ec2c8b46fa" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0000000000010000" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_b7a19fcd-15ba-41ba-a3d7-dc352d5f79ba" Name="b7a19fcd-15ba-41ba-a3d7-dc352d5f79ba" NonPagedMemory="true" Strict="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_e13c0d23-ccbc-4e12-931b-d9cc2eee27e4" Name="e13c0d23-ccbc-4e12-931b-d9cc2eee27e4" NonPagedMemory="true" Level="3">
<Keywords>
<Keyword Value="0x0000000000020098" />
</Keywords>
<CaptureStateOnSave Timeout="30">
<Keyword Value="0x0000000000020118" />
</CaptureStateOnSave>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_d49918cf-9489-4bf1-9d7b-014d864cf71f" Name="d49918cf-9489-4bf1-9d7b-014d864cf71f" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_e6835967-e0d2-41fb-bcec-58387404e25a" Name="e6835967-e0d2-41fb-bcec-58387404e25a" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0000000000000001" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_c4636a1e-7986-4646-bf10-7bc3b4a76e8e" Name="c4636a1e-7986-4646-bf10-7bc3b4a76e8e" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_314de49f-ce63-4779-ba2b-d616f6963a88" Name="314de49f-ce63-4779-ba2b-d616f6963a88" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_8c416c79-d49b-4f01-a467-e56d3aa8234c" Name="8c416c79-d49b-4f01-a467-e56d3aa8234c" NonPagedMemory="true" Stack="true">
<Keywords>
<Keyword Value="0x0000000000402000" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_e7ef96be-969f-414f-97d7-3ddb7b558ccc" Name="e7ef96be-969f-414f-97d7-3ddb7b558ccc" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0000000000002000" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_9580d7dd-0379-4658-9870-d5be7d52d6de" Name="9580d7dd-0379-4658-9870-d5be7d52d6de" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0000000000000200" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_8e92deef-5e17-413b-b927-59b2f06a3cfc" Name="8e92deef-5e17-413b-b927-59b2f06a3cfc" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_e4b70372-261f-4c54-8fa6-a5a7914d73da" Name="e4b70372-261f-4c54-8fa6-a5a7914d73da" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_0a002690-3839-4e3a-b3b6-96d8df868d99" Name="0a002690-3839-4e3a-b3b6-96d8df868d99" NonPagedMemory="true" Level="3" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_cfeb0608-330e-4410-b00d-56d8da9986e6" Name="cfeb0608-330e-4410-b00d-56d8da9986e6" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_751ef305-6c6e-4fed-b847-02ef79d26aef" Name="751ef305-6c6e-4fed-b847-02ef79d26aef" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_65cd4c8a-0848-4583-92a0-31c0fbaf00c0" Name="65cd4c8a-0848-4583-92a0-31c0fbaf00c0" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x000000000000002f" />
</Keywords>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_ca11c036-0102-4a2d-a6ad-f03cfed5d3c9" Name="ca11c036-0102-4a2d-a6ad-f03cfed5d3c9" NonPagedMemory="true" Stack="true" Level="3">
<Keywords>
<Keyword Value="0x000000000000000f" />
</Keywords>
<CaptureStateOnStart Timeout="30">
<Keyword Value="0x000000000000000f" />
</CaptureStateOnStart>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_7e7d3382-023c-43cb-95d2-6f0ca6d70381" Name="7e7d3382-023c-43cb-95d2-6f0ca6d70381" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0000000000000001" />
</Keywords>
<CaptureStateOnStart Timeout="30">
<Keyword Value="0x0000000000000001" />
</CaptureStateOnStart>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_db6f6ddb-ac77-4e88-8253-819df9bbf140" Name="db6f6ddb-ac77-4e88-8253-819df9bbf140" NonPagedMemory="true" Stack="true" Level="3">
<Keywords>
<Keyword Value="0x000000000000000f" />
</Keywords>
<CaptureStateOnStart Timeout="30">
<Keyword Value="0x000000000000000f" />
</CaptureStateOnStart>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_802ec45a-1e99-4b83-9920-87c98277ba9d" Name="802ec45a-1e99-4b83-9920-87c98277ba9d" NonPagedMemory="true" Stack="true" Level="3" Strict="true">
<Keywords>
<Keyword Value="0x0000000000000277" />
</Keywords>
<CaptureStateOnStart Timeout="30">
<Keyword Value="0x0000000000000277" />
</CaptureStateOnStart>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_a688ee40-d8d9-4736-b6f9-6b74935ba3b1" Name="a688ee40-d8d9-4736-b6f9-6b74935ba3b1" NonPagedMemory="true" Level="3">
<Keywords>
<Keyword Value="0x000000000000ffff" />
</Keywords>
<CaptureStateOnStart Timeout="30">
<Keyword Value="0x000000000000ffff" />
</CaptureStateOnStart>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_83ed54f0-4d48-4e45-b16e-726ffd1fa4af" Name="83ed54f0-4d48-4e45-b16e-726ffd1fa4af" NonPagedMemory="true" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_6ad52b32-d609-4be9-ae07-ce8dae937e39" Name="6ad52b32-d609-4be9-ae07-ce8dae937e39" NonPagedMemory="true" Stack="true" Level="3" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_d8975f88-7ddb-4ed0-91bf-3adf48c48e0c" Name="d8975f88-7ddb-4ed0-91bf-3adf48c48e0c" NonPagedMemory="true" Stack="true" Level="3" />
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_a669021c-c450-4609-a035-5af59af4df18_CaptureState" Name="a669021c-c450-4609-a035-5af59af4df18" NonPagedMemory="true" Level="3" CaptureStateOnly="true">
<CaptureStateOnSave Timeout="30">
<Keyword Value="0x0000000000020118" />
</CaptureStateOnSave>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_ce8dee0b-d539-4000-b0f8-77bed049c590_CaptureState" Name="ce8dee0b-d539-4000-b0f8-77bed049c590" NonPagedMemory="true" CaptureStateOnly="true">
<CaptureStateOnSave Timeout="30">
<Keyword Value="0xffffffffffffffff" />
</CaptureStateOnSave>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_0f67e49f-fe51-4e9f-b490-6f2948cc6027_CaptureState" Name="0f67e49f-fe51-4e9f-b490-6f2948cc6027" NonPagedMemory="true" CaptureStateOnly="true">
<CaptureStateOnSave Timeout="30">
<Keyword Value="0xffffffffffffffff" />
</CaptureStateOnSave>
</EventProvider>
<EventProvider Id="WPR_initiated_WprApp_WPR_Event_Collector_8c416c79-d49b-4f01-a467-e56d3aa8234c_CaptureState" Name="8c416c79-d49b-4f01-a467-e56d3aa8234c" NonPagedMemory="true" Stack="true" CaptureStateOnly="true">
<CaptureStateOnSave Timeout="30">
<Keyword Value="0x0000000000080000" />
</CaptureStateOnSave>
</EventProvider>
<HeapEventProvider Id="WPR_initiated_WprApp_WPR_Internal_Heap_Collector_Provider">
<HeapProcessIds>
<HeapProcessId Value="0" />
</HeapProcessIds>
</HeapEventProvider>
<Profile Id="CPUDiskIOFileIOGPUHeap.Verbose.File" Name="CPUDiskIOFileIOGPUHeap" Description="RunningProfile:DiskIO.Verbose.File, FileIO.Verbose.File, GPU.Verbose.File, Heap.Verbose.File, CPU.Verbose.File" LoggingMode="File" DetailLevel="Verbose">
<ProblemCategories>
<ProblemCategory Value="Resource Analysis" />
</ProblemCategories>
<Collectors>
<SystemCollectorId Value="WPR_initiated_WprApp_WPR_System_Collector">
<SystemProviderId Value="WPR_initiated_WprApp_WPR_System_Collector_Provider" />
</SystemCollectorId>
<EventCollectorId Value="WPR_initiated_WprApp_WPR_Event_Collector">
<EventProviders>
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_b675ec37-bdb6-4648-bc92-f3fdc74d3ca2" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_57277741-3638-4a4b-bdba-0ac6e45da56c" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_36b6f488-aad7-48c2-afe3-d4ec2c8b46fa" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_b7a19fcd-15ba-41ba-a3d7-dc352d5f79ba" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_e13c0d23-ccbc-4e12-931b-d9cc2eee27e4" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_d49918cf-9489-4bf1-9d7b-014d864cf71f" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_e6835967-e0d2-41fb-bcec-58387404e25a" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_c4636a1e-7986-4646-bf10-7bc3b4a76e8e" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_314de49f-ce63-4779-ba2b-d616f6963a88" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_8c416c79-d49b-4f01-a467-e56d3aa8234c" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_e7ef96be-969f-414f-97d7-3ddb7b558ccc" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_9580d7dd-0379-4658-9870-d5be7d52d6de" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_8e92deef-5e17-413b-b927-59b2f06a3cfc" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_e4b70372-261f-4c54-8fa6-a5a7914d73da" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_0a002690-3839-4e3a-b3b6-96d8df868d99" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_cfeb0608-330e-4410-b00d-56d8da9986e6" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_751ef305-6c6e-4fed-b847-02ef79d26aef" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_65cd4c8a-0848-4583-92a0-31c0fbaf00c0" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_ca11c036-0102-4a2d-a6ad-f03cfed5d3c9" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_7e7d3382-023c-43cb-95d2-6f0ca6d70381" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_db6f6ddb-ac77-4e88-8253-819df9bbf140" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_802ec45a-1e99-4b83-9920-87c98277ba9d" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_a688ee40-d8d9-4736-b6f9-6b74935ba3b1" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_83ed54f0-4d48-4e45-b16e-726ffd1fa4af" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_6ad52b32-d609-4be9-ae07-ce8dae937e39" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_d8975f88-7ddb-4ed0-91bf-3adf48c48e0c" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_a669021c-c450-4609-a035-5af59af4df18_CaptureState" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_ce8dee0b-d539-4000-b0f8-77bed049c590_CaptureState" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_0f67e49f-fe51-4e9f-b490-6f2948cc6027_CaptureState" />
<EventProviderId Value="WPR_initiated_WprApp_WPR_Event_Collector_8c416c79-d49b-4f01-a467-e56d3aa8234c_CaptureState" />
<!-- ===== 关键:追加这3个 ===== -->
<EventProviderId Value="KernelProcess"/>
<EventProviderId Value="KernelMemory"/>
<EventProviderId Value="KernelThread"/>
</EventProviders>
</EventCollectorId>
<HeapEventCollectorId Value="WPR_initiated_WprApp_WPR_Internal_Heap_Collector">
<HeapEventProviders>
<HeapEventProviderId Value="WPR_initiated_WprApp_WPR_Internal_Heap_Collector_Provider" />
</HeapEventProviders>
</HeapEventCollectorId>
</Collectors>
<TraceMergeProperties>
<TraceMergeProperty Id="BaseVerboseTraceMergeProperties" Name="BaseTraceMergeProperties">
<DeletePreMergedTraceFiles Value="true" />
<FileCompression Value="false" />
<InjectOnly Value="false" />
<SkipMerge Value="false" />
<CustomEvents>
<CustomEvent Value="ImageId" />
<CustomEvent Value="BuildInfo" />
<CustomEvent Value="VolumeMapping" />
<CustomEvent Value="EventMetadata" />
<CustomEvent Value="PerfTrackMetadata" />
<CustomEvent Value="WinSAT" />
<CustomEvent Value="NetworkInterface" />
</CustomEvents>
</TraceMergeProperty>
</TraceMergeProperties>
</Profile>
</Profiles>
</WindowsPerformanceRecorder>

脚本录制完成会生成一个 etl 文件,点击 save 保存文件,这个文件可以直接用 wpa.exe 打开。


点击 Open in WPA,直接启动 wpa.exe


WPA 界面如下图:

把一堆内存地址瞬间翻译成人类可读的函数名/文件名/行号的唯一钥匙。没有它,你看到的将永远是 :

符号路径 = 把 “地址” 翻译成 “代码” 的翻译器。有了它,同一行立刻变成 :

添加方法:选择 Trace->configure Symbol Paths 里选中符号数据->勾选 LoadSymbols。

点击需要的左侧内容浏览器中想分析的内容进行展开

双击任意图表,展开系统活动性中进程时间线分析窗口

选择需要的图表,File->Export package->保存到本地

查看者电脑预先安装好对应版本的 wpa 工具,直接打开接收的 outPut.wpapk 文件,即可打开查看性能测试图表。

NVIDIA Nsight Systems 是一款系统级性能分析工具, 它提供了一个跨 CPU 和 GPU 的统一时间线视图 。
如何工作:
1.同时录制 CPU 和 GPU 的活动。
2.在时间线界面上,你会看到并排的轨道:
CPU 轨道: 显示每个 CPU 线程的活动。
GPU 轨道: 显示 GPU 上各个引擎的活动(主要是 Graphics 图形引擎和 Compute 计算引擎)。
File-->new File,图中红框位置选择需要测试的应用程序,设置工作空间保存路径,点击 Start 录制

点击 save 保存,等待生成最终图表文件

识别 GPU 空闲间隙: 在 GPU 轨道上,你会看到一条条连续的色块(表示 GPU 正在工作),色块之间的空白就是 GPU 空闲 时间。
关联 CPU 活动: 将时间线放大,对准 GPU 的空闲间隙,然后向上看同一时间点的 CPU 线程在做什么。
场景 A:GPU 空等 CPU
在 GPU 空闲间隙里,你发现 CPU 主线程正在执行一些非提交命令的任务(比如在忙别的逻辑,或者卡在某个函数里)。这说明 CPU 没有及时为 GPU 准备好下一帧的命令。
WPA 验证: 在 WPA 中分析这个时间段,你会看到那个 CPU 线程的繁忙状态,并利用符号和调用栈找到具体是哪个函数或模块耗时过长。
场景 B:CPU 空等 GPU
CPU 线程很早就向 GPU 提交了一个非常耗时的命令(比如一个复杂的着色器或计算核函数),然后调用了同步函数,导致 CPU 线程被阻塞(进入睡眠状态),直到 GPU 完成任务。
在 Nsight Systems 上: 你会看到 CPU 线程有一段 “空白”(睡眠),而与此同时 GPU 正在满负荷工作。
WPA 验证: 在 WPA 中,你会看到该线程在同步调用上花费了大量等待时间。
解释:内存泄漏指程序中动态分配的内存,在使用完毕后没有被正确释放,导致这部分内存永远无法再被程序访问或回收,导致可用内存越来越少。系统内存被耗尽,无法再分配新内存,程序可能因为内存溢出(OOM)崩溃或被系统杀掉。
参考图表:Virtual Memory Snapshots

执行操作:进入软件操作视图,开启 WPR 脚本录制工具,频繁打开、关闭大文件,采集样本。
采集完成,打开 WPA 工具,设置好符号(设置方式见 WPA 使用)
双击 memory -> Virtual Memory Snapshots 图表,Analysis 视图,鼠标悬浮 Virtual Memory Snapshots 表头,放出以下字段:
Process:进程名称。
EndTime (Internal use) (s):数据采样点时间戳。
Working Set (MB):正在使用的物理工作内存。
Private Working Set (MB):工作中的私有内存。
Commit (MB):提交内存。
Virtual Size (MB):进程地址空间。
关闭文件,Working Set、Private Working Set、Commit 均降低,则排除内存泄漏。
关闭文件,Private Working Set 一直增长、Commit 开始降低,则存在内存泄漏。
性能场景:组件库资源布设、模型复制、移动、旋转,CPU 低占用,但是软件很卡。
CPU Usage (Precise)、File I/O

启动被测软件-->启动 WPR 脚本录制工具,采集样本-->频繁布置、打开模型,等待操作完成-->保存录制数据。
打开 WPA 工具,设置好符号(设置方式见 WPA 使用)。
核心关注被测应用 在追踪时间段内的 线程级 CPU 使用与调用栈热点。

BimBase 主进程 : CPU Usage: 19461 ms , Ready: 1541ms , Waits: 84715 ms , % CPU Usage: 0.74%
1. CPU 使用率极低
BimBase 主进程占用 CPU 时间仅 19461ms,占比 0.74%
→ 进程 Waits: 84715 ms 处于 “等待” 状态,而非 “计算瓶颈”
2. 等待时间极长
BimBase 主进 程 等待了 84715 ms 秒,占总时长(19461+84715=104176)的 81.32%
进 程被阻塞,不是因为 CPU 忙,而是 其他事件。
3. 结论
在整个追踪期间 CPU 使用率 非常低 ,BIMBase.exe 进程 81% 时间卡在等待状态,说明当前阶段进程处于 “空闲” 被 “I/O 或者消息阻塞” 状态,而非计算密集型任务。
1. 下一步,结合 IO 图或者 GPU 图进行进一步分析,若为用户空闲阶段,则无需优化,属于正常行为。 若 I/O 图显示此时正在大量读模型文件说明 CPU 在等磁塞 。
2. 查看 File I/O Duration by Process 视图,查看 BIMBase.exe 在整个追踪时间段内的 文件 I/O 操作耗时分布。
I/O 耗时堆叠图 + 明细表

3. 结论:
1. 单次读取耗时:≈ 0.0177 ms ,写入耗时: ≈ 0.131ms,6213 次读取,8780 次写入,总耗时≈ 3.2 秒
“平均单次读取耗时” 公式:单次耗时 = 总耗时 ÷ IRP 次数,3215ms÷ 6213 =0.518ms;
→ 极高频率、极小块、极快响应
→ 磁盘随机读取性能瓶颈已非常明显,
b. I/O 操作总量极大 , 总 IRP 次数:约 6213 次 , 总 I/O 耗时:约 3 秒
典型的 “小块随机读取” 模型,机械盘 IOPS 直接打满 。
c. CPU 图联合验证:CPU 空闲,I/O 爆满
CPU 图显示:进程等待 85 秒
I/O 图显示:14993 次 I/O,平均单次 0.214 ms
CPU 不是瓶颈,磁盘 IOPS( 每秒读写次数 ) 是瓶颈
主线程可能在等 “异步 I/O 完成事件” 或 “消息循环”,数据加载慢 。
4. 怎么看出的机械盘 IOPS 直接打满?
1. 先算 BIMBase 实际产生的 IOPS , 从图中:
2. 总 I/O 次数:≈ 60297 次(Read + Create + QueryInfo + Close + ...)总时间:85 秒 → 实际 IOPS =60297÷ 85 ≈ 709 次/秒
3. 再看机械盘的 IOPS 上限(常识值)

4. 对比结果:实际 IOPS 机械盘上限 80~120 次/s,远小于 NeXusPlatform.exe 进程的 709 次/s
5. 机械盘队列会打满,每次 I/O 延迟从 0.01 ms 涨到 1~100 ms, 用户感觉就是 “加载慢”、“卡顿”。

6. 打开 “Hard Page Faults” 视图 → 如果 Fault 次数与 Disk usage I/O 高峰重合(DISK 紫色 线条),说明 内存缺页 + 磁盘阻塞 。

与开发沟通了解到,BIM 相关的软件,在进行模型文件创建时,为了保证模型文件的一致性、唯一性,行业内一般都采用单线程去进行文件读写,所以会造成这个问题,优化建议:

性能场景:打开大文件完毕,进行构件选中、远近景构件查看,软件卡顿。
参考:Nsight Systems 视图,核心现象:CPU 帧时间远超目标,直接导致卡顿, 目标帧率为 60Hz(每帧理论最大耗时 16.67ms),但实际 CPU 帧持续时间高达 34.6ms (标注 “34.6 ms”),远超目标值。这直接导致画面卡顿(“Stutter”),是性能问题的最直观表现。

上图标注了多个线程(如[10088] nvvvgf2umx.dll、[14892] nvvvgf2umx.dll、[18824] nvvvgf2umx.dll等)处于“Blocked State”(阻塞状态),且关联到 ETW 事件(Microsoft-Windows-DxgKml)。结合下图的 CPU 核心利用率图表(黑白线条),推测这些线程可能因以下原因被阻塞:
cudaDeviceSynchronize)。下图图的时间线视图中,CPU 核心利用率(顶部黑白线条)与 GPU 操作(中部绿色条带)的时间重叠度较低。结合上图的 “Queue [13.009s]”“Queue [12.181s]” 等长耗时队列,说明:

CPU 未能及时向 GPU 提交任务(如渲染命令、内存传输),CPU 处于繁忙状态,性能瓶颈在 CPU。进一步分析 CPU 瓶颈,WPA 打开 Nsight Systems 视图生成的 etl 文件,这个就是前面说的: 性能优化的核心思路 --- 多工具联动,从不同维度透视问题 。

从图表中 “Idle Thread 占比 87.5%”(第二张图)和 “CPU 利用率波动但整体未满载”(第一张图)的线索看,系统整体 CPU 资源未被充分利用。问题不是出在:GPU、CPU 上。这个时候需要开发排查是否局部线程调度低效或关键进程/线程被阻塞。


打开项目文件,按照设置条件循环创建立方体、圆柱、球体,检测到闪退事件或者崩溃事件,打包本地日志到云存储服务器,重新进行长时间运行测试。
第一步:检测到崩溃事件,打包本地:D:\安装目录\根目录\logs 文件夹为 zip。
第二步:上传 zip 文件至云存储服务器,增加时间戳作为唯一文件名称。
第三步:删除本地 logs 文件下所有日志文件。
第四步:启动软件继续自动执行稳定性测试用例。
检查本地进程是否存活:(http://localhost:8028/api/nexus/status)
手动触发日志上传:(http://localhost:8028/api/nexus/upload-logs)