调查性能计数器 (dotnet-counters)

本文适用于: ✔️ dotnet-counters 版本 3.0.47001 及更高版本。

可以从运行 .NET 5 或更高版本的应用程序读取计数器。

安装

可通过三种方法下载和使用 dotnet-counters

  • 一次性执行(建议):

    从 .NET 10.0.100 开始,可以使用 dotnet-countersdnx

    dnx dotnet-counters [options]
    

    例如:

    dnx dotnet-counters monitor --process-id 1234
    

    此方法会自动下载并运行最新版本,而无需永久修改系统。

  • dotnet 全局工具:

    若要安装最新版本的 dotnet-countersNuGet 包 以供频繁使用,请使用 dotnet 工具安装 命令:

    dotnet tool install --global dotnet-counters
    

    此命令将 dotnet-counters 二进制文件安装到 .NET SDK 工具路径,可将其添加到 PATH,以便轻松调用全局安装的工具。

  • 直接下载:

    下载与平台相匹配的工具可执行文件:

    (OS) 平台
    Windows x86 | x64 | 手臂 | Arm-x64
    Linux x64 | 手臂 | Arm64 | musl-x64 | musl-Arm64

注意

若要在 x86 应用上使用 dotnet-counters,需要使用相应的 x86 版本的工具。

摘要

dotnet-counters [-h|--help] [--version] <command>

描述

dotnet-counters 是一个性能监视工具,用于临时运行状况监视和初级性能调查。 它可以观察通过 EventCounter API 或 Meter API 发布的性能计数器值。 例如,可以快速监视 CPU 使用情况或 .NET Core 应用程序中引发的异常率,以了解在使用 PerfViewdotnet-trace 深入调查更严重的性能问题之前是否有任何可疑操作。

选项

  • --version

    显示实用工具的版本 dotnet-counters

  • -h|--help

    显示命令行帮助。

命令

命令
dotnet-counters collect
dotnet-counters monitor
dotnet-counters ps

dotnet-counters collect

定期收集所选计数器的值,并将它们导出为指定的文件格式以进行后续处理。

摘要

dotnet-counters collect [-h|--help] [-p|--process-id] [-n|--name] [--diagnostic-port] [--refresh-interval] [--counters <COUNTERS>] [--format] [-o|--output] [-- <command>]

选项

  • -p|--process-id <PID>

    要从中收集计数器数据的进程的 ID。

    注意

    在 Linux 和 macOS 上,使用此选项需要目标应用程序并 dotnet-counters 共享相同的 TMPDIR 环境变量。 否则,该命令将超时。

  • -n|--name <name>

    要从中收集计数器数据的进程的名称。

    注意

    在 Linux 和 macOS 上,使用此选项需要目标应用程序并 dotnet-counters 共享相同的 TMPDIR 环境变量。 否则,该命令将超时。

  • --diagnostic-port <port-address[,(listen|connect)]>

    设置用于与要监视的进程通信的 诊断端口dotnet-counters 目标进程内的 .NET 运行时必须就端口地址达成一致,一个侦听,另一个连接。 dotnet-counters使用或--process-id选项附加--name时,或者使用-- <command>选项启动进程时,自动确定正确的端口。 通常需要在等待将来启动的进程或与不在当前进程命名空间的容器中运行的进程通信时显式指定端口。

    OS port-address 的不同之处在于:

    • Linux 和 macOS - Unix 域套接字的路径,例如 /foo/tool1.socket
    • Windows - 命名管道的路径,例如 \\.\pipe\my_diag_port1
    • Android、iOS 和 tvOS - IP:port,例如 127.0.0.1:9000

    默认情况下, dotnet-counters 侦听指定地址。 可以通过在地址后面追加dotnet-counters来请求,connect连接。 例如, --diagnostic-port /foo/tool1.socket,connect 将连接到侦听 Unix 域套接字的 /foo/tool1.socket .NET 运行时进程。

    有关如何使用此选项从应用启动启动监视计数器的信息,请参阅 使用诊断端口

  • --refresh-interval <SECONDS>

    更新显示的计数器之间延迟的秒数

  • --counters <COUNTERS>

    计数器的逗号分隔列表。 计数器可以指定为 provider_name[:counter_name]。 如果使用 provider_name 时没有限定的计数器列表,则显示来自提供程序的所有计数器。 若要发现提供程序和计数器名称,请参阅 内置指标。 对于 EventCountersprovider_name 是 EventSource 的名称,对于 Meterprovider_name 是计量的名称。

  • --format <csv|json>

    要导出的格式。 当前可用的格式:csv 和 json。

  • -o|--output <output>

    输出文件的名称。

  • -- <command>

    集合配置参数后,用户可以追加 -- 一个命令来启动 .NET 应用程序。 dotnet-counters 使用提供的命令启动进程并收集请求的指标。 这通常可用于收集应用程序的启动路径的指标,并可用于诊断或监视在主要入口点之前或不久发生的问题。

    注意

    使用此选项监视第一个与该工具通信的 .NET 进程,这意味着,如果命令启动多个 .NET 应用程序,它只会收集第一个应用。 因此,建议在独立应用程序或使用该 dotnet exec <app.dll> 选项时使用此选项。

    注意

    如果通过 dotnet-counters它启动 .NET 可执行文件,则会重定向其输入/输出,并且无法与其 stdin/stdout 交互。 可以通过 Ctrl+C 或 SIGTERM 退出该工具,以安全地结束该工具和子进程。 如果子进程在工具之前退出,工具也将退出。 如果需要使用 stdin/stdout,可以使用 --diagnostic-port 选项。 有关详细信息,请参阅 “使用诊断端口”。

注意

若要使用 dotnet-counters 收集指标,需要以与运行目标进程的用户相同的用户身份或以根身份运行。 否则,该工具将无法与目标进程建立连接。

示例

  • 以 3 秒的刷新间隔时间收集所有计数器的值,并生成 csv 输出文件:

    > dotnet-counters collect --process-id 1902 --refresh-interval 3 --format csv
    
    --counters is unspecified. Monitoring System.Runtime counters by default.
    Starting a counter session. Press Q to quit.
    
  • dotnet mvc.dll 作为子进程启动,开始从启动中收集运行时计算器和 ASP.NET Core Hosting 计算器,并将其另存为 JSON 输出:

    > dotnet-counters collect --format json --counters System.Runtime,Microsoft.AspNetCore.Hosting -- dotnet mvc.dll
    Starting a counter session. Press Q to quit.
    File saved to counter.json
    

dotnet-counters monitor

显示所选计数器的定期刷新值。

摘要

dotnet-counters monitor [-h|--help] [-p|--process-id] [-n|--name] [--diagnostic-port] [--refresh-interval] [--counters] [-- <command>]

选项

  • -p|--process-id <PID>

    要监视的进程的 ID。

  • -n|--name <name>

    要监视的进程的名称。

  • --diagnostic-port

    要创建的诊断端口的名称。 请参阅使用诊断端口,了解如何使用此选项从应用启动时开始监视计数器。

  • --refresh-interval <SECONDS>

    更新显示的计数器之间延迟的秒数

  • --counters <COUNTERS>

    计数器的逗号分隔列表。 计数器可以指定为 provider_name[:counter_name]。 如果使用 provider_name 时没有限定的计数器列表,则显示来自提供程序的所有计数器。 若要发现提供程序和计数器名称,请参阅 内置指标。 对于 EventCountersprovider_name 是 EventSource 的名称,对于 Meterprovider_name 是计量的名称。

  • -- <command>

    集合配置参数后,可以追加 -- 一个命令来启动 .NET 应用程序。 dotnet-counters 将启动一个进程,并监视请求的指标。 这通常可用于收集应用程序的启动路径的指标,并可用于诊断或监视在主要入口点之前或不久发生的问题。

    注意

    使用此选项监视第一个与该工具通信的 .NET 进程,这意味着,如果命令启动多个 .NET 应用程序,它只会收集第一个应用。 因此,建议在独立应用程序或使用该 dotnet exec <app.dll> 选项时使用此选项。

    注意

    通过 dotnet-counters 启动 .NET 可执行文件将重定向其输入/输出,并且无法与其 stdin/stdout 交互。 可以通过 Ctrl+C 或 SIGTERM 退出该工具,以安全地结束该工具和子进程。 如果子进程在工具之前退出,工具也将退出。 如果需要使用 stdin/stdout,可以使用 --diagnostic-port 选项。 有关详细信息,请参阅 “使用诊断端口”。

注意

在 Linux 和 macOS 上,此命令需要目标应用程序和 dotnet-counters 使用同一 TMPDIR 环境变量。

注意

若要使用 dotnet-counters 监视指标,需要以与运行目标进程的用户相同的用户身份或以根身份运行。

注意

如果看到类似于以下错误消息: [ERROR] System.ComponentModel.Win32Exception (299): A 32 bit processes cannot access modules of a 64 bit process.尝试对目标进程使用 dotnet-counters 该错误消息的位数不匹配。 请务必在安装链接中下载工具的正确位数。

示例

  • 以 3 秒的刷新间隔监视 System.Runtime 中的所有计数器:

    > dotnet-counters monitor --process-id 1902  --refresh-interval 3 --counters System.Runtime
    Press p to pause, r to resume, q to quit.
        Status: Running
    Name                                              Current Value
    [System.Runtime]
        dotnet.assembly.count ({assembly})                               115
        dotnet.gc.collections ({collection})
            gc.heap.generation
            ------------------
            gen0                                                           5
            gen1                                                           1
            gen2                                                           1
        dotnet.gc.heap.total_allocated (By)                       1.6947e+08
        dotnet.gc.last_collection.heap.fragmentation.size (By)
            gc.heap.generation
            ------------------
            gen0                                                           0
            gen1                                                     348,248
            gen2                                                           0
            loh                                                           32
            poh                                                            0
        dotnet.gc.last_collection.heap.size (By)
            gc.heap.generation
            ------------------
            gen0                                                           0
            gen1                                                  18,010,920
            gen2                                                   5,065,600
            loh                                                       98,384
            poh                                                    3,407,048
        dotnet.gc.last_collection.memory.committed_size (By)      66,842,624
        dotnet.gc.pause.time (s)                                           0.05
        dotnet.jit.compilation.time (s)                                    1.317
        dotnet.jit.compiled_il.size (By)                             574,886
        dotnet.jit.compiled_methods ({method})                         6,008
        dotnet.monitor.lock_contentions ({contention})                   194
        dotnet.process.cpu.count ({cpu})                                  16
        dotnet.process.cpu.time (s)
            cpu.mode
            --------
            system                                                         4.953
            user                                                           6.266
        dotnet.process.memory.working_set (By)                             1.3217e+08
        dotnet.thread_pool.queue.length ({work_item})                      0
        dotnet.thread_pool.thread.count ({thread})                       133
        dotnet.thread_pool.work_item.count ({work_item})              71,188
        dotnet.timer.count ({timer})                                     124
    

    注意

    如果应用使用 .NET 版本 8 或更低版本, 则这些版本中不存在 System.Runtime 计量 ,并且 dotnet-counters 会回退以显示较旧的 System.Runtime EventCounters 。 UI 看起来略有不同,如下所示。

    [System.Runtime]
          % Time in GC since last GC (%)                                 0
          Allocation Rate (B / 1 sec)                                5,376
          CPU Usage (%)                                                  0
          Exception Count (Count / 1 sec)                                0
          GC Fragmentation (%)                                          48.467
          GC Heap Size (MB)                                              0
          Gen 0 GC Count (Count / 1 sec)                                 1
          Gen 0 Size (B)                                                24
          Gen 1 GC Count (Count / 1 sec)                                 1
          Gen 1 Size (B)                                                24
          Gen 2 GC Count (Count / 1 sec)                                 1
          Gen 2 Size (B)                                           272,000
          IL Bytes Jitted (B)                                       19,449
          LOH Size (B)                                              19,640
          Monitor Lock Contention Count (Count / 1 sec)                  0
          Number of Active Timers                                        0
          Number of Assemblies Loaded                                    7
          Number of Methods Jitted                                     166
          POH (Pinned Object Heap) Size (B)                             24
          ThreadPool Completed Work Item Count (Count / 1 sec)           0
          ThreadPool Queue Length                                        0
          ThreadPool Thread Count                                        2
          Working Set (MB)                                              19
    
  • 仅监视垃圾回收和垃圾回收堆分配来源 System.Runtime

    > dotnet-counters monitor --process-id 1902 --counters System.Runtime[dotnet.gc.collections,dotnet.gc.heap.total_allocated]
    
    Press p to pause, r to resume, q to quit.
    Status: Running
    
    Name                                  Current Value
    [System.Runtime]
        dotnet.gc.collections ({collection})
            gc.heap.generation
            ------------------
            gen0                                0
            gen1                                0
            gen2                                0
        dotnet.gc.heap.total_allocated (By)     9,943,384
    
    
  • 监视用户定义的 EventCounter 中的 EventSource 值。 有关详细信息,请参阅教程:使用 .NET Core 中的 EventCounters 衡量性能

    > dotnet-counters monitor --process-id 1902 --counters Samples-EventCounterDemos-Minimal
    
    Press p to pause, r to resume, q to quit.
        request                                      100
    
  • 启动 my-aspnet-server.exe 和监视从其启动时加载的程序集数:

    > dotnet-counters monitor --counters System.Runtime[dotnet.assembly.count] -- my-aspnet-server.exe
    Press p to pause, r to resume, q to quit.
    Status: Running
    
    Name                               Current Value
    [System.Runtime]
    dotnet.assembly.count ({assembly})      11
    
  • 启动并my-aspnet-server.exearg1作为命令行参数启动arg2,并从其启动时监视其工作集和 GC 堆大小:

    > dotnet-counters monitor --counters System.Runtime[dotnet.process.memory.working_set,dotnet.gc.last_collection.heap.size] -- my-aspnet-server.exe arg1 arg2
    
    Name                                             Current Value
    [System.Runtime]
        dotnet.gc.last_collection.heap.size (By)
            gc.heap.generation
            ------------------
            gen0                                          560
            gen1                                      462,720
            gen2                                            0
            loh                                             0
            poh                                         8,184
        dotnet.process.memory.working_set (By)     48,431,104
    
    

dotnet-counters ps

列出可由 dotnet-counters 监视的 dotnet 进程。 dotnet-counters 版本 6.0.320703 及更高版本还显示每个进程的命令行参数(如果可用)。

摘要

dotnet-counters ps [-h|--help]

示例

假设使用命令 dotnet run --configuration Release 启动长时间运行的应用。 在另一个窗口中,运行 dotnet-counters ps 命令。 看到的输出如下所示。 命令行参数(如果有)显示在 dotnet-counters 版本 6.0.320703 及更高版本中。

> dotnet-counters ps

  21932 dotnet     C:\Program Files\dotnet\dotnet.exe   run --configuration Release
  36656 dotnet     C:\Program Files\dotnet\dotnet.exe

使用诊断端口

诊断端口 是一项运行时功能,可用于开始监视或从应用启动收集计数器。 dotnet-counters为此,可以使用前面的示例中所述使用dotnet-counters <collect|monitor> -- <command>,也可以使用--diagnostic-port该选项。

使用 dotnet-counters <collect|monitor> -- <command> 以子进程的形式启动应用程序,是从启动时开始对其进行快速监视的最简单方法。

但是,如果想要更好地控制所监视应用的生存期(例如,仅在前 10 分钟内监视应用并继续执行),或者如果需要使用 CLI 与应用进行交互,则使用 --diagnostic-port 选项可以同时控制要监视的目标应用和 dotnet-counters

  1. 以下命令创建 dotnet-counters 名为 myport.sock 并等待连接的诊断套接字。

    dotnet-counters collect --diagnostic-port myport.sock
    

    输出:

    Waiting for connection on myport.sock
    Start an application with the following environment variable: DOTNET_DiagnosticPorts=/home/user/myport.sock
    
  2. 在单独的控制台中,通过将环境变量 DOTNET_DiagnosticPorts 设置为 dotnet-counters 输出中的值,启动目标应用程序。

    export DOTNET_DiagnosticPorts=/home/user/myport.sock
    ./my-dotnet-app arg1 arg2
    

    这样,便可以 dotnet-counters 开始收集以下时间的 my-dotnet-app计数器:

    Waiting for connection on myport.sock
    Start an application with the following environment variable: DOTNET_DiagnosticPorts=myport.sock
    Starting a counter session. Press Q to quit.
    

    重要

    使用 dotnet run 启动应用可能会有问题,因为 dotnet CLI 可能会生成许多子进程,这些子进程不是你的应用,并且可以在应用之前连接到 dotnet-counters 该应用,从而使你的应用在运行时挂起。 建议直接使用应用的自包含版本或用于 dotnet exec 启动应用程序。