通过分析 CPU 使用情况衡量应用程序性能(C#、Visual Basic、C++、F#)

使用集成了调试器的“CPU 使用率”诊断工具时,查找性能问题。 还可以在没有附加调试器的情况下或以正在运行的应用为目标来分析 CPU 使用情况。 有关详细信息,请参阅运行带或不带调试器的分析工具

调试中断时,“诊断工具”窗口中的“CPU 使用率”工具收集有关应用程序中正在执行的函数的信息。 该工具将列出执行工作的函数,并提供时间线图,可专用于采样会话的特定部分。

重要

Visual Studio 中的 .NET 开发(包括 ASP.NET、ASP.NET Core 和本机/C++ 开发)支持集成了调试器的诊断工具。 需要相应的 Visual Studio 工作负载。 要运行带调试器的分析工具(“诊断工具”窗口),需具备 Windows 8 及更高版本。

在本教程中,你将:

  • 收集 CPU 使用量数据
  • 分析 CPU 使用量数据

如果“CPU 使用率”未提供所需数据,则“性能探查器”中的其他分析工具可提供可能有帮助的不同种类的信息。 在许多情况下,CPU 以外的因素可能会导致应用程序性能瓶颈,例如内存、呈现 UI 或网络请求时间。

步骤 1:收集 CPU 使用情况数据

  1. 打开要在 Visual Studio 中调试的项目,并在应用中设置检查 CPU 使用率的断点。

  2. 在函数末尾或想要分析的代码区域中设置第二个断点。

    通过设置两个断点,可将数据收集限制到想要分析的代码部分。

  3. 将自动显示 “诊断工具” 窗口,除非你已将其关闭。 若要再次显示该窗口,请依次单击“调试” >“Windows” >“显示诊断工具” 。

  4. 可以使用工具栏上的“选择工具”设置,选择是否查看 CPU 使用率内存使用或同时查看两者。 如果运行的是 Visual Studio Enterprise,还可以在“工具”>“选项”>“IntelliTrace”中启用或禁用 IntelliTrace。

    Screenshot that shows Diagnostics Tools.

    Screenshot that shows Diagnostics Tools.

    我们将主要查看 CPU 使用率,因此请确保已启用CPU 使用率(默认情况下已启用)。

  5. 依次单击“调试” >“启动调试” 或单击工具栏上的“启动” 或按 F5 。

    当应用完成加载后,将显示诊断工具的“摘要”视图。 如果需要打开窗口,请依次单击“调试”>“Windows”>“显示诊断工具”。

    Screenshot that shows Diagnostics Tools Summary Tab.

    Screenshot that shows Diagnostics Tools Summary Tab.

    有关事件的详细信息,请参阅搜索和筛选“诊断工具”窗口中的“事件”选项卡

  6. 运行会触发第一个断点的方案。

  7. 调试器暂停时,启用收集 CPU 使用率数据,然后打开“CPU 使用率”选项卡。

    Screenshot that shows Diagnostics Tools enable CPU profiling.

    Screenshot that shows Diagnostics Tools enable CPU profiling.

    选择“记录 CPU 配置文件”时,Visual Studio 将开始记录函数和执行这些函数所用的时间。 应用程序在断点处中断时,仅可以查看此收集的数据。

  8. 按 F5 将应用运行到第二个断点。

    现在将拥有应用程序特定于在两个断点间运行的代码区域的性能数据。

    探查器开始准备线程数据。 等待其完成。

    Screenshot that shows Diagnostics Tools preparing threads.

    Screenshot that shows Diagnostics Tools preparing threads.

    CPU 使用率工具在“CPU 使用率” 选项卡中显示报表。

    Screenshot that shows Diagnostics Tools CPU Usage Tab.

    Screenshot that shows Diagnostics Tools CPU Usage Tab.

  9. 如果想要选择要分析的更具体的代码区域,请在 CPU 时间轴中选择一个区域(它必须是显示分析数据的区域)。

    Screenshot that shows Diagnostics Tools selecting a time segment.

    Screenshot that shows Diagnostics Tools selecting a time segment.

    现在可以开始分析数据。 如果在收集或显示数据时遇到问题,请参阅排查分析错误并修复问题

    提示

    尝试确定性能问题时,需要获取多个度量值。 性能在运行间自然变化,并且由于加载 Dll、JIT 编译方法和初始化缓存等一次性的初始化工作,代码路径在首次运行时的执行速度通常较缓慢。 通过获取多个度量值,你可以更好地了解所显示指标的范围和中值,从而可比较首次与稳定状态下代码区域的性能。

步骤 2:分析 CPU 使用量数据

建议通过检查 CPU 使用率下的函数列表开始分析数据,然后确定执行大部分工作的函数,最后仔细查看每一个函数。

  1. 在函数列表中,检查执行大部分工作的函数。

    Screenshot that shows Diagnostics Tools CPU Usage Function List.

    Screenshot that shows Diagnostics Tools CPU Usage Function List.

    提示

    函数将按执行工作量从多到少排列(不按调用顺序)。 这有助于快速标识运行时间最长的函数。

  2. 在函数列表中,双击一个执行大量工作的应用函数。

    双击该函数时,将在左侧窗格中打开“函数”视图。 从下拉菜单中选择“调用方/被调用方”视图。

    Screenshot that shows Diagnostics Tools Caller Callee View.

    在此视图中,所选函数显示在标题和“当前函数”框中(本例中为 DoWork)。 调用当前函数的函数显示在“调用函数”左下方,当前函数调用的任何函数均显示在右侧的“被调用函数”框中。 (可选择其中一个框来更改当前函数。)

    此视图显示总时间及函数完成执行所用的总体应用运行时间的百分比。 函数体还显示函数体中所用的时间总量(及百分比),其中不包括调用和被调用函数中所用的时间。

    双击该函数时,将在左侧窗格中打开“调用方/被调用方”视图。

    Screenshot that shows Diagnostics Tools Caller Callee View.

    在此视图中,所选函数显示在标题和“当前函数”框中(本例中为 GetNumber)。 调用当前函数的函数显示在“调用函数”左下方,当前函数调用的任何函数均显示在右侧的“被调用函数”框中。 (可选择其中一个框来更改当前函数。)

    此视图显示总时间及函数完成执行所用的总体应用运行时间的百分比。 函数体还显示函数体中所用的时间总量(及百分比),其中不包括调用和被调用函数中所用的时间。 (在此示例中,共花费 2389 毫秒,函数体内花费 2367 毫秒,其余 22 毫秒花费在此函数调用的外部代码中)。

    提示

    函数体中的较高值可能指示函数自身内部的性能瓶颈。

  3. 若要按调用函数的顺序来查看较高级别的视图,请在顶部窗格的下拉列表中选择“调用关系树”。

    图中每个带编号的区域都与过程中的一个步骤相关。

    Diagnostics Tools Call Tree

    映像 说明
    Step 1 CPU 使用量调用关系树中的顶级节点是一个伪节点
    Step 2 在大多数应用中,当禁用 “显示外部代码” 选项时,二级节点是 [外部代码] 节点,该节点包含系统和框架代码,它可以启动和停止应用、绘制 UI、控制线程计划以及向应用提供其他低级服务。
    Step 3 二级节点的子级为用户代码方法和异步例程,它们由二级系统和框架代码进行调用或创建。
    Step 4 方法的子节点仅包含用于父方法调用的数据。 禁用“显示外部代码” 后,应用方法只能包含 [外部代码] 节点。

    下面是列值的详细信息:

    • 总 CPU 指示函数及由它调用的任何函数完成的工作量。 较高的总 CPU 值指向总体成本最高的函数。

    • 自 CPU指示函数体中的代码完成的工作量,不包括由它调用的函数完成的工作。 较高的自 CPU 值可能指示函数自身内部的性能瓶颈。

    • 模块包含函数的模块名或包含 [外部代码] 节点中的函数的模块数量。

    要查看调用树视图中使用最高 CPU 百分比的函数调用,请单击“展开热路径”。

    Screenshot that shows Diagnostics Tools Hot Path.

    注意

    如果看到调用树中的代码标记为“已损坏”代码或“不可走堆栈”,则表示可能已删除 Windows事件跟踪 (ETW) 事件。 尝试第二次收集相同的跟踪以解决问题。

查看外部代码

外部代码是你编写的代码执行的系统和框架组件中的函数。 外部代码包含函数,可启动和停止应用、绘制 UI、控制线程以及向应用提供其他低级别服务。 在大多数情况下,你不会对外部代码感兴趣,因此 CPU 使用率工具可将用户方法的外部函数收集到一个 [外部代码] 节点中。

若要查看外部代码的调用路径,请从“筛选器视图”列表中选择“显示外部代码”,然后选择“应用”。

Screenshot that shows Choose Filter View, then Show External Code.

请注意,许多外部代码调用链已深度嵌套,因此函数名列的宽度可能超过所有计算机监视器(最大的计算机监视器除外)的显示宽度。 发生这种情况时,函数名将显示为 […]。

使用搜索框找到要查找的节点,然后滑动水平滚动条将数据带入视图中。

提示

如果分析调用 Windows 函数的外部代码,应确保具有最新的 .pdb 文件。 如果没有这些文件,报告视图将列出含义隐晦、难以理解的 Windows 函数名称。 有关如何确保具有所需文件的详细信息,请参阅在调试器中指定符号 (.pdb) 和源文件

后续步骤

本教程中介绍了如何收集和分析 CPU 使用量数据。 如果已完成探查器教程,可能需要了解使用分析工具优化代码的一般方法。

在本教程中,你了解了如何在调试时收集和分析 CPU 使用情况数据。 你可能想要详细了解如何使用性能探查器分析发布版本。