使用 PerfCollect 跟踪 .NET 应用程序

本文适用于:✔️ .NET Core 2.1 SDK 及更高版本

在 Linux 上遇到性能问题时,可以通过使用 perfcollect 来进行跟踪,从而收集有关问题时机器上具体情况的详细信息。

perfcollect 是一个 bash 脚本,它使用 Linux Trace Toolkit:下一代(LTTng) 收集从运行时或任何 EventSource 写入的事件,并使用 perf 收集目标进程的 CPU 样本。

准备计算机

按照以下步骤准备你的计算机以使用 perfcollect 收集性能跟踪。

注释

如果要从容器内部捕获,则容器必须具有相应的功能。 所需的最少功能是 PERFMONSYS_PTRACE。 如果使用最小集合进行捕获失败,请将 SYS_ADMIN 功能添加到容器中。 有关使用 PerfCollect 跟踪容器内应用程序的详细信息,请参阅 收集容器中的诊断

  1. 下载 perfcollect

    curl -OL https://aka.ms/perfcollect
    
  2. 使脚本可执行。

    chmod +x perfcollect
    
  3. 安装跟踪先决条件 - 这些是实际的跟踪库。

    sudo ./perfcollect install
    

    这将在计算机上安装以下先决条件:

    1. perf:Linux 性能事件子系统和配套用户模式集合/查看器应用程序。 perf 是 Linux 内核源的一部分,但通常不会默认安装。
    2. LTTng:用于捕获 CoreCLR 在运行时发出的事件数据。 然后,此数据用于分析各种运行时组件的行为,例如 GC、JIT 和线程池。

最新版本的 .NET Core 和 Linux 性能工具支持自动解析框架代码的方法名称。

若要解析本机运行时 DLL 的方法名称(例如 libcoreclr.so),perfcollect 将在转换数据时为其解析符号,但前提是存在这些二进制文件的符号。 请参阅“获取本机运行时的符号”部分以获取详细信息。

收集跟踪

  1. 有两个 shell 可用 - 一个用于控制跟踪,称为 [跟踪],一个用于运行应用程序,称为 [应用]

  2. [Trace]:启动收集。

    sudo ./perfcollect collect sampleTrace
    

    预期输出:

    Collection started.  Press CTRL+C to stop.
    

    注释

    LTTng 在版本 2.12 和 2.13 之间发生了重大更改。 .NET 运行时当前支持版本 2.12。 如果 Linux 分发版采用 2.13 或更高版本,则建议禁用 perfcollect 功能的 LTTng 部分。 为此,请将选项“-nolttng”添加到 perfcollect 命令行,并在步骤 3 中不设置DOTNET_EnableEventLog环境变量。

  3. [应用] 使用以下环境变量设置应用程序外壳 - 这可实现 CoreCLR 的跟踪配置。

  4. [应用] 使用以下环境变量设置应用程序外壳 - 这可实现 CoreCLR 的跟踪配置。

    export DOTNET_PerfMapEnabled=1
    export DOTNET_EnableEventLog=1
    

    注释

    在使用 .NET 7 执行应用时,除了设置上述环境变量外,还必须设置 DOTNET_EnableWriteXorExecute=0。 例如:

    export DOTNET_EnableWriteXorExecute=0
    

    注释

    .NET 6 将用于配置 .NET 运行时行为的环境变量的前缀标准化为 DOTNET_,而不是 COMPlus_。 但是,COMPlus_ 前缀仍可继续使用。 如果使用的是 .NET 运行时的早期版本,则仍应对环境变量使用 COMPlus_ 前缀。

  5. [应用] 运行应用 - 让它运行直到你认为合适,以便捕获性能问题。 所需的长度可以很短,只要它能充分涵盖你想调查的性能问题发生的时间段。

    dotnet run
    
  6. [跟踪] 停止收集 - 按 Ctrl+C

    ^C
    ...STOPPED.
        Starting post-processing. This may take some time.
        Generating native image symbol files
    ...SKIPPED
    Saving native symbols
    ...FINISHED
    Exporting perf.data file
    ...FINISHED
    Compressing trace files
    ...FINISHED
    Cleaning up artifacts
    ...FINISHED
        Trace saved to sampleTrace.trace.zip
    

    压缩跟踪文件现在存储在当前工作目录中。

查看跟踪

有许多选项可用于查看收集的跟踪。 最好使用 Windows 上的 PerfView 查看跟踪,但也可以直接在 Linux 上使用 PerfCollectTraceCompass 查看跟踪。

使用 PerfCollect 查看跟踪文件

你可以使用 perfcollect 本身来查看收集的跟踪。 为此,请使用以下命令:

./perfcollect view sampleTrace.trace.zip

默认情况下,这将显示使用perf的应用程序的 CPU 跟踪。

若要查看通过 LTTng收集的事件,可以传入标志 -viewer lttng 以查看各个事件:

./perfcollect view sampleTrace.trace.zip -viewer lttng

这将使用 babeltrace 查看器打印事件有效负载:

# [01:02:18.189217659] (+0.020132603) ubuntu-xenial DotNETRuntime:ExceptionThrown_V1: { cpu_id = 0 }, { ExceptionType = "System.Exception", ExceptionMessage = "An exception happened", ExceptionEIP = 139875671834775, ExceptionHRESULT = 2148734208, ExceptionFlags = 16, ClrInstanceID = 0 }
# [01:02:18.189250227] (+0.020165171) ubuntu-xenial DotNETRuntime:ExceptionCatchStart: { cpu_id = 0 }, { EntryEIP = 139873639728404, MethodID = 139873626968120, MethodName = "void [helloworld] helloworld.Program::Main(string[])", ClrInstanceID = 0 }

使用 PerfView 打开跟踪文件

若要查看 CPU 示例和事件的聚合视图,可以在 Windows 计算机上使用 PerfView

  1. 将 trace.zip 文件从 Linux 复制到 Windows 计算机。

  2. https://aka.ms/perfview 下载 PerfView。

  3. 运行 PerfView.exe

    PerfView.exe <path to trace.zip file>
    

PerfView 将显示基于跟踪文件中包含的数据支持的视图列表。

  • 对于 CPU 调查,请选择“CPU 堆栈”
  • 有关详细的 GC 信息,请选择 GCStats
  • 对于每个进程/模块/方法 JIT 信息,请选择 JITStats
  • 如果没有所需信息的视图,可以尝试在原始事件视图中查找事件。 选择 “事件”。

有关如何解释 PerfView 中的视图的详细信息,请参阅视图本身中的帮助链接,或从 PerfView 的主窗口中选择“帮助用户>指南”。

注释

通过 System.Diagnostics.Tracing.EventSource API 编写的事件(包括框架中的事件)不会在其提供程序名称下显示。 相反,它们作为 EventSourceEvent 事件写入在 Microsoft-Windows-DotNETRuntime 提供程序之下,并且它们的有效负载被 JSON 序列化。

注释

如果在方法名称和调用堆栈中看到 [unknown] /memfd:doublemapper 帧,请先设置 DOTNET_EnableWriteXorExecute=0 ,然后再运行用 perfcollect 跟踪的应用程序。

使用 TraceCompass 打开跟踪文件

Eclipse TraceCompass 是可用于查看跟踪的另一个选项。 TraceCompass 也适用于 Linux 计算机,因此无需将跟踪移到 Windows 计算机。 要使用TraceCompass打开跟踪文件,您需要解压缩该文件。

unzip myTrace.trace.zip

perfcollect 将它收集的 LTTng 跟踪保存在 lttngTrace 中的子目录中的 CTF 文件格式中。 具体而言,CTF 文件将位于如下所示 lttngTrace/auto-20201025-101230\ust\uid\1000\64-bit\的目录中。

可以通过选择 File -> Open Trace 打开 TraceCompass 中的 CTF 跟踪文件,然后选择 metadata 文件。

有关更多详细信息,请参阅 TraceCompass 文档

获取本机运行时的符号

大多数情况下,你感兴趣的是自己的代码,perfcollect 默认解析这些代码。 有时,查看 .NET DLL(这是最后一节的内容)中发生的情况很有用,但有时本机运行时 dll(通常 libcoreclr.so)中发生的情况很有趣。 perfcollect 在转换其数据时将解析这些符号,但前提是存在这些本机 DLL 的符号(并且位于它们所对应的库的旁边)。

有一个名为 dotnet-symbol 的全局命令可以执行此作。 若要使用 dotnet-symbol 获取本机运行时符号,

  1. 安装 dotnet-symbol

    dotnet tool install -g dotnet-symbol
    
  2. 下载符号。 如果安装的 .NET Core 运行时版本为 2.1.0,则执行此作的命令为:

    mkdir mySymbols
    dotnet symbol --symbols --output mySymbols  /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0/lib*.so
    
  3. 将符号复制到正确的位置。

    sudo cp mySymbols/* /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0
    

    如果由于没有对相应目录的写入访问权限而无法完成此操作,可以使用 perf buildid-cache 添加符号。

此后,当你运行 perfcollect 时,应获取本机 dll 的符号名称。

在 Docker 容器内收集

有关如何在容器环境中使用 perfcollect 的详细信息,请参阅 在容器中收集诊断

详细了解收集选项

可以指定以下可选标志 perfcollect ,以便更好地满足诊断需求。

在特定的时间内收集

如果要在特定持续时间内收集跟踪,可以使用 -collectsec 选项后跟一个数字,指定收集跟踪的总秒数。

收集线程时间跟踪

指定 -threadtimeperfcollect 可以收集每线程的 CPU 使用率数据。 这样,便可以分析每个线程花费 CPU 时间的位置。

收集托管内存和垃圾回收器性能的跟踪

以下选项可让你专门收集运行时中的 GC 事件。

  • perfcollect collect -gccollectonly

仅收集一组最少的 GC 收集事件。 这是最不详细的 GC 事件收集配置文件,对目标应用的性能影响最低。 此命令类似于 PerfView.exe /GCCollectOnly collect PerfView 中的命令。

  • perfcollect collect -gconly

收集更详细的 GC 收集事件,包括 JIT、加载程序和异常事件。 这会请求更详细的事件(例如分配信息和 GC 联接信息),对目标应用性能产生的影响比 -gccollectonly 选项产生的影响更大。 此命令类似于 PerfView.exe /GCOnly collect PerfView 中的命令。

  • perfcollect collect -gcwithheap

收集最详细的 GC 收集事件(用于跟踪堆的存活和移动情况)。 这会对 GC 行为进行深入分析,但会对性能产生较大的影响,因为每个 GC 都可能需要两倍的时间。 建议了解在生产环境中跟踪时使用此跟踪选项的性能影响。