C#/.NET 性能诊断工具链深度评测:dotnet-counters、dotnet-trace、dotnet-dump、dotnet-gcdump 实战对比(2026)

📝 254 字 · ☕ 1 分钟阅读

🔗 压测相关:2026年压测工具深度横评:k6 vs wrk vs hey vs vegeta vs oha — 五个工具逐个实测,选对工具性能调优才刚开始。

先讲个凌晨三点的故事

那天晚上我在群里被 @ 醒,说线上一个 .NET 服务响应从 50ms 涨到了 2 秒,内存还在匀速往上爬。我第一反应是 ssh 上去 top 一下,好家伙 CPU 直接 180%,GC 一秒好几次。

然后呢?然后我对着这个进程干瞪眼。Java 有 jstack、jmap,Python 有 py-spy,.NET 我居然不知道从哪下手。后来才把官方这套诊断工具链用明白——今天就把 dotnet-counters、dotnet-trace、dotnet-dump、dotnet-gcdump、dotnet-monitor 这五个家伙的实战体验一次说清楚。

五个工具分别是什么

1. dotnet-counters:先看全局,别瞎猜

这是我最先推荐的工具,没有之一。它就像 Linux 的 top,实时打印进程的性能计数器,但比 top 细得多:CPU 占用、托管堆大小、Gen0/1/2 的 GC 次数、异常抛出数、线程池队列长度,全都有。

dotnet-counters monitor -p 12345 --counters System.Runtime

输出长这样(大概意思):

CPU Usage (%)                      62.3
Working Set (MB)                  1024.5
GC Heap Size (MB)                  512.7
Gen 0 GC Count                      120
Gen 1 GC Count                       30
Gen 2 GC Count                        8
ThreadPool Queue Length               0
Exceptions Count                     45

看到 Gen 2 GC 一分钟 8 次,心里就有数了——这是内存压力大的信号,不是 CPU 问题。工具开销极小(官方说 < 1% CPU),生产环境直接开没问题,这是它的最大优势。

优点:零侵入、开销低、上手零门槛,5 分钟就能看懂。缺点:只能看”现在发生了什么”,看不出”为什么发生”。

2. dotnet-trace:要火焰图,就找它

当你确定 CPU 高或者 GC 频繁,想定位到具体方法时,上 dotnet-trace。它采集事件级数据,类似 Linux 的 perf,支持直接导出火焰图。

dotnet-trace collect -p 12345 --format flamegraph

跑 30 秒,Ctrl+C 停掉,它会生成一个火焰图 HTML。我那次 CPU 180% 的排查,火焰图一出来直接锁定了罪魁祸首——一个日志库在热路径上做字符串拼接,占了 40% 的 CPU。之前猜了半小时”是不是 GC 问题”,火焰图 10 秒打脸。

优点:能精准定位热点方法、GC 分配点,出图直观。缺点:开销比 counters 大(一般 1-3% CPU),适合短时间采集;需要稍微看懂火焰图。

3. dotnet-dump:生产环境最安全的”事后分析”

很多故障是偶发的:你盯着的时候它好好的,你一走它就崩。这时候 dotnet-dump 是王牌——把进程快照抓下来,然后慢慢分析,不打扰线上。

dotnet-dump collect -p 12345
dotnet-dump analyze core_20260809_1.dmp

进入分析模式后,常用的 SOS 命令:

clrstack          # 看托管线程栈
dumpheap -stat    # 看堆上对象统计
gcroot <地址>     # 看对象被谁引用

之前排查一个内存泄漏,就是 dump 下来后 dumpheap -stat 发现有一类缓存对象占了 3GB,再 gcroot 追到引用链,发现是 ConcurrentDictionary 只写不清理。这工具我在Python 内存泄漏排查那篇里说的思路一样——先看堆,再追引用,只是 .NET 这边用 SOS 命令。

优点:快照后离线分析,零风险;能查托管线程、堆对象、引用链。缺点:文件大(几 GB 常见),分析需要懂点 SOS 命令,学习曲线最陡。

4. dotnet-gcdump:只想查托管内存,用这个更轻

如果你确定问题就是内存(GC 堆涨、Gen2 频繁),不一定非要 dump 那么重的东西。dotnet-gcdump 只抓 GC 堆快照,文件小一个量级,打开也快。

dotnet-gcdump collect -p 12345

生成的 .gcdump 文件可以用 Visual Studio 打开,看对象类型分布、大对象堆、引用关系,非常直观。我查”哪个类型吃掉了内存”优先用这个,比 dump 快多了。这也呼应了之前聊过的C# Span 零分配优化——分配少了,gcdump 里自然干净。

优点:轻量、快、Visual Studio 可视化友好。缺点:只看得到托管堆,查不了线程栈和 CPU 热点。

5. dotnet-monitor:容器环境的神器

现在服务基本都跑在 Docker/K8s 里,上面那些工具都得进容器执行,命令可能没有,权限可能不够。dotnet-monitor 就是为这个场景生的:它作为 sidecar 或者直接嵌在应用里,暴露 HTTP 端点,远程就能抓 metrics、dump、gcdump、trace。

curl http://localhost:52325/metrics          # Prometheus 格式指标
curl -X POST http://localhost:52325/dump      # 远程抓 dump
curl -X POST http://localhost:52325/gcdump    # 远程抓 gcdump

在 K8s 里配合 Prometheus 采集,你甚至能在 Grafana 上直接看 GC 指标。生产排障不用再”进容器敲命令”了。

优点:远程诊断、容器原生、指标可对接监控系统。缺点:多一个组件要运维;配置稍微复杂。

核心对比表

工具 解决什么问题 开销 上手难度 最适用场景
dotnet-counters 实时指标总览 <1% CPU ★☆☆☆☆ 故障第一站,先看全局
dotnet-trace CPU 热点 / GC 事件 1-3% CPU ★★☆☆☆ 定位热点方法,出火焰图
dotnet-dump 线程栈 / 堆 / 引用链 抓取时暂停毫秒级 ★★★★☆ 偶发故障、内存泄漏深挖
dotnet-gcdump GC 堆对象分布 很轻 ★★☆☆☆ 内存问题快速定位类型
dotnet-monitor 容器远程诊断 ★★★☆☆ K8s / Docker 生产环境

我的实战决策路径

总结成一套固定流程,遇到 .NET 性能问题直接照着走:

  1. 先 counters 看全局:CPU 高?内存涨?GC 频繁?异常多?—— 定方向。
  2. CPU 高 → trace:30 秒火焰图,锁定热点方法。
  3. 内存涨 → gcdump:看 GC 堆里谁在膨胀,快速定位类型。
  4. 还查不清 → dump:线程栈 + 引用链,深挖根因。
  5. 容器环境 → monitor:全程远程操作,不碰容器。

这套流程和之前写过的C# LINQ 性能优化C# Channel 高吞吐的排查思路是一脉相承的:先量化,再定位,最后优化。区别只是这次工具链齐了。

对了,图像化一点看这几个工具的分工:

.NET性能诊断工具定位矩阵:dotnet-counters、dotnet-trace、dotnet-monitor、dotnet-dump、dotnet-gcdump 按诊断时机与粒度分布
.NET 诊断工具定位矩阵:横轴是诊断时机,纵轴是诊断粒度

常见问题(FAQ)

Q: 这些工具在生产环境直接跑安全吗?

dotnet-counters 和 dotnet-monitor 的指标采集开销极小,可以长期开。dotnet-trace 建议短时间(30秒-几分钟)采集。dotnet-dump 抓取瞬间进程会暂停几十毫秒到几百毫秒,对大多数服务可以接受,但大内存进程(10GB+)抓取前最好评估一下。

Q: 一定要装 Visual Studio 吗?

不用。除了 dotnet-gcdump 的可视化分析建议用 VS 外,其他工具都是命令行,dotnet-dump 用 SOS 命令分析,dotnet-trace 直接出火焰图 HTML,服务器上装个 dotnet-diagnostic-tools 的 dotnet tool 就行。

Q: .NET Framework 老项目能用吗?

dotnet-counters、dotnet-trace 等主要支持 .NET Core 3.0+。老 .NET Framework 项目可以退而求其次:用 procdump 抓 dump,配合 WinDbg 的 SOS 扩展分析,思路一样,命令略有差异。

Q: 工具在哪装?

都是 dotnet tool,一条命令的事:dotnet tool install -g dotnet-counters / dotnet-trace / dotnet-dump / dotnet-gcdump。dotnet-monitor 是独立的 NuGet 包或容器镜像。前提是目标机有 .NET SDK 或运行时。

总结

工具这东西,最怕的是”知道名字但不知道什么时候用”。我的建议很直接:先把 dotnet-counters 练熟,它是所有排查的第一站;再学会 dotnet-gcdump,内存问题十有八九够用;火焰图和 dump 是进阶,遇到棘手问题再上。

之前写Linux perf 火焰图eBPF bpftrace的时候说过,排查能力是工程师的硬通货。这套 .NET 工具链补上之后,从系统层到应用层,你的武器库算是齐了。下次凌晨三点被叫醒,至少不用对着 top 干瞪眼了。

📤 分享这篇文章