开始调查应用中的性能问题的好方法之一是使用 CPU 探查器了解其 CPU 使用率。 Visual Studio 的 CPU 使用率性能工具显示 C++、C#/Visual Basic 中执行代码所花费的 CPU 活动计算时间和百分比。
CPU 使用情况工具可帮助你:
诊断团队代码库中的慢速或进程挂起。 该工具可帮助你诊断团队生产代码出现的问题。 它提供数据的自动见解和各种视图,以便分析和诊断性能问题。
识别 DevOps 方案中的性能问题 例如,当客户报告在旺季期间某些请求或订单未通过零售网站时,该工具会有所帮助。 通常,问题在生产中,并且目前很难进行调试,但此工具可以帮助你捕获问题的足够信息和证据。 收集跟踪文件后,分析可以快速帮助你了解潜在原因,并在代码上下文中提供建议,以便你可以执行后续步骤来解决此问题。
检查是否存在高 CPU 使用率 如果 API 请求中不存在延迟问题,则可以使用 CPU 使用率工具检查是否存在高 CPU 使用率和其他相关问题。 CPU 使用率工具可帮助你确定瓶颈,让你可以缩小优化的范围。
CPU 使用情况工具对本地跟踪会话和生产都很有用。 可以采用以下方法运行 CPU 使用率工具:使用键盘快捷键 Alt+F2,然后选择“CPU 使用率”,或使用 dotnet-trace 或 dotnet-monitor 等工具打开已收集的跟踪。 (对于 .NET 生产代码,这是最有可能选择的跟踪收集方式。)
“CPU 使用率”工具可以在打开的 Visual Studio 项目、在已安装的 Microsoft Store 应用上运行,也可以附加到正在运行的应用或进程。 可以在发布或调试版本上运行 CPU 使用率工具。 有关详细信息,请参阅在发行版本或调试版本上运行分析工具。
以下说明介绍如何使用不带调试器的“CPU 使用情况”工具以及 Visual Studio“性能探查器” 。 示例使用本地计算机上的发布版本。 发布版本提供了实际应用性能的最佳视图。 有关演示如何使用 CPU 使用情况工具提高性能的教程,请参阅案例研究 - 初学者代码优化指南。
通常,本地计算机最好复制已安装的应用执行。 要从远程设备收集数据,请直接在该设备上运行应用,而不通过使用远程桌面连接运行。
收集 CPU 使用率数据
在 Visual Studio 项目中,将解决方案配置设置为 “发布 ”并选择部署目标。
部署目标通常与项目名称匹配,指示本地部署。
选择“调试”“性能探查器” 。
在“可用工具”下,选择“CPU 使用情况”,然后选择“启动” 。
如果在启动探查器之前启用了“在暂停后开始收集”选项,则在诊断会话视图中选择“记录”按钮之前,不会收集数据。
注意
对于某些项目类型(如 CMake),必须将启动目标设置为 “可执行文件”。 有关详细信息,请参阅我的项目支持哪些工具? 若要详细了解如何提高此工具的效率,请参阅优化探查器设置。
应用启动后,诊断会话即会开始,并显示 CPU 使用率数据。 完成收集数据后,选择“停止收集”。
CPU 使用量工具可分析数据并显示报告。 如果在收集或显示数据时遇到问题,请参阅排查分析错误并修复问题。
使用“筛选器”下拉列表以选择或取消选择要显示的线程,并使用“搜索”框搜索特定线程或节点 。
CPU 使用率数据列
| 名称 | 描述 |
|---|---|
| CPU 总量 [单位,以百分数计算] |
调用函数所使用的 CPU 计算时间毫秒数和 CPU 百分比,以及函数在所选时间范围内调用的函数。 这与“CPU 利用率”时间线图不同,后者是将时间范围内的 CPU 总活动量与可用 CPU 总量进行比较。 |
| 自 CPU [单位,以百分数计算] |
调用函数在所选时间范围内所使用的 CPU 计算时间毫秒数和 CPU 百分比,不包括函数调用的函数。 |
| 模块 | 在某些视图中会显示“模块”列,该列显示包含函数的模块的名称。 |
分析 CPU 见解
如果顶级见解部分显示任何见解,请使用提供的链接获取有关所标识问题的详细信息。 此外,如果使用 Copilot,询问 Copilot 按钮将打开 Copilot 聊天窗口,Copilot 将根据代码和任何已识别的问题提供建议。
有关详细信息,请参阅 CPU 见解。
分析 CPU 使用率
若要深入分析 CPU 使用情况报告,请先打开其中一个详细的报告视图:
单击报表摘要页中的 “打开详细信息 ”,或选择其中一个顶部函数以打开 “函数 ”视图。
从 “当前视图” 列表中,可以选择一个详细的报表视图。
下表提供了详细视图的说明。
| 查看 | 描述 |
|---|---|
| 调用方/被调用方 | 特定函数的 CPU 时间详细视图,以及调用此函数和被其调用的函数。 性能数据已在数据收集期间聚合。 可以选择调用函数和被调用函数以遍历调用路径。 |
| 调用树 | 函数调用路径的分层视图。 用于标识占用最多 CPU 时间(热路径)的调用路径。 |
| 模块 | 各个模块中所用的 CPU 时间的视图,该时间已在数据收集期间进行汇总。 用于识别可能由于高调用次数和/或性能问题的结合而导致性能瓶颈的模块。 |
| Functions | 各个函数中所用的 CPU 时间的视图,该时间已在数据收集期间进行汇总。 用于识别可能由于高调用次数和/或性能问题而成为性能瓶颈的函数。 |
| 火焰图 | 火焰图可视化中函数调用路径的分层视图。 用于标识占用最多 CPU 时间(热路径)的调用路径。 |
在除调用方/被调用方之外的所有视图中,诊断报告按“CPU 总量”从最高到最低进行排序。 通过选择列标题更改排序顺序或排序列。 可以双击感兴趣的函数,将看到该函数的源,并且该函数中所用时间的分布情况会突出显示。 该表显示包含数据(例如函数中所用的时间)的列,包括所调用的函数(总 CPU),以及显示函数中所用时间的另一列,不包括调用的函数(自 CPU)。
此数据可以帮助评估函数本身是否属于性能瓶颈。 确定方法显示的数据量,看看第三方代码或运行时库是否是终结点速度慢或资源消耗量大的原因。
有关使用火焰图的详细信息,请参阅使用火焰图识别热路径。
CPU 使用率调用关系树
要查看调用关系树,请选择报表中的父节点。 默认情况下,“CPU 使用情况”页面将打开“调用方/被调用方”视图。 在“当前视图”下拉列表中,选择“调用树” 。
可以单击“展开热路径”和“显示热路径”按钮,以查看调用树视图中使用最高 CPU 百分比的函数调用。
调用关系树结构
| 图像 | 描述 |
|---|---|
|
CPU 使用率调用关系树中的顶级节点,表示应用程序。 |
|
在大多数应用中,当“显示外部代码”选项处于禁用状态时,第二级别节点就是“[外部代码]”节点 。 该节点包含启动和停止应用、绘制 UI、控制线程计划以及向应用提供其他低级别服务的系统和框架代码。 |
|
二级节点的子级为用户代码方法和异步例程,它们由二级系统和框架代码进行调用或创建。 |
|
方法的子节点仅有父方法调用的数据。 禁用“显示外部代码” 后,应用方法只能包含 [外部代码] 节点。 |
若要帮助了解调用树中的意外数据,请参阅 “了解调用树”。
外部代码
由代码执行的系统和框架函数称为“外部代码”。 外部代码函数启动和停止应用、绘制 UI、控制线程以及向应用提供其他低级别服务。 在大多数情况下,你不会对外部代码感兴趣,因此 CPU 使用情况调用树可将用户方法的外部函数收集到一个[外部调用]节点中。
要查看外部代码的调用路径,请在主报告摘要页面(右窗格)上的“设置”下拉列表中取消选择“仅显示我的代码”,然后选择“应用”。 (设置下拉菜单在主报告摘要页面上可用,在详细视图上不可用。)
禁用“仅显示我的代码”时,“CPU 使用率”页面的“调用树”视图将展开外部代码调用。
许多外部代码调用链都是深度嵌套的,因此链的宽度可能超过“函数名”列的显示宽度。 然后,函数名称如下图所示。
要查找所需的函数名称,请使用搜索框。 将鼠标悬停在所选行上或使用水平滚动条来查看数据。
CPU 使用情况调用树中的异步函数
当编译器遇到异步方法时,它会创建一个隐藏的类来控制方法的执行。 从概念上讲,此类是状态机。 该类具有编译器生成的异步调用原始方法以及运行其所需的回调、计划程序和迭代器的函数。 当父方法调用原始方法时,编译器将从父方法的执行上下文中删除该方法,并在控制应用执行的系统和框架代码的上下文中运行隐藏的类方法。 异步方法通常(但不总是)在一个或多个不同线程上执行。 此代码在“CPU 使用情况”调用树中显示为“[外部代码]”节点的子节点,位于树的顶部节点下面 。
展开生成的方法,以显示正在进行的操作:
分析多进程性能
从 Visual Studio 2022 版本 17.13 开始,可以在 CPU 使用情况工具中分析多进程数据。 这样,分析多进程应用(如 .NET Aspire)的性能就更容易了。 借助此功能,可以在单个会话中跨进程区分和分析 CPU 利用率,从而更清楚地了解资源消耗情况。
需要先收集多进程数据,然后才能对其进行分析。 若要收集数据,请在“性能探查器”中为 CPU 使用率工具选择从多个进程中收集数据。
显示应用的 CPU 使用率的时间线图显示每个进程具有不同颜色编码的性能数据。 该图形显示为堆积面积图。
可以使用 CPU 时间线图左上角的下拉列表筛选进程。 选择或取消选择某个进程时,探查器摘要页和详细报告会根据新选择进行更新,从而实现更精确的分析。
收集调用计数 (.NET)
如果要在“函数”视图中查看调用计数,可以在启动探查器之前启用设置。 .NET 项目类型支持此设置,并且需要在探查器下启动进程。 不支持附加方案。
在性能探查器中,选择 CPU 使用率的“设置”图标。
启用“收集调用计数(仅 .NET)”选项。
收集 CPU 使用率数据。
打开“函数”视图,并确保“调用计数”列设置为可见。
如果看不到该列,请右键单击列标题以选择可见列。