关键在采集时机、provider配置和事件粒度匹配:默认附加跟踪不捕获jit/gc事件,需显式指定microsoft-windows-dotnetruntime:4:4等provider;冷启动须用dotnet trace collect -- 同步采集;离线分析依赖pdb符号文件才能显示方法名。

直接用 dotnet-trace 采集性能数据,不等于就能定位到真实瓶颈——关键在采集时机、Provider 配置和事件粒度是否匹配问题场景。盲目全量采集只会生成超大 trace.nettrace 文件,反而掩盖热点。
对运行中进程附加跟踪时,为什么经常采不到 JIT 或 GC 事件?
默认 dotnet trace collect --process-id <pid></pid> 启用的是基础运行时事件集,但 JIT 编译、GC 堆快照、ThreadPool 队列变化等关键事件需要显式启用对应 Provider。
- 必须加
--providers Microsoft-Windows-DotNETRuntime:4:4才能捕获 GC 生命周期、代际提升、暂停时间等完整信息 - JIT 相关事件(如方法编译、内联决策)需额外指定
Microsoft-Windows-DotNETRuntime-JIT:4:4,否则只看到“Unknown Method”堆栈 - Linux/macOS 上若想获取高精度 CPU 样本(非 wall-clock 时间),得用
Microsoft-DotNETCore-SampleProfiler:0x0000000000000001:4,且进程需以COMPlus_PerfMapEnabled=1环境变量启动 - Windows 上若目标进程是 .NET Framework 应用(非 .NET Core+),
dotnet-trace完全不适用,得换PerfView或 ETW 工具
启动新进程时同步采集,如何避免漏掉冷启动阶段的关键事件?
冷启动阶段(如依赖注入容器构建、配置加载、静态构造函数执行)极易被忽略,因为默认采集从 dotnet trace collect 命令执行后才开始,而此时应用可能已初始化完毕。
- 必须用
dotnet trace collect -- <app.dll></app.dll>形式,而非先dotnet run再 attach——前者让dotnet-trace在子进程 fork 后立即注册 EventPipe 监听器 - 若应用有长耗时的初始化逻辑(如预热缓存、加载大模型),建议加
--duration 120并手动触发业务动作后再结束采集,确保覆盖完整生命周期 - 不要依赖
dotnet run默认的Debug模式编译结果——Release 模式下 JIT 行为、内联策略、调试符号剥离都会影响事件语义,PDB 缺失会导致方法名显示为???
离线分析 trace.nettrace 时,Chrome Trace Format 转换为何有时看不到自定义方法?
dotnet trace convert 生成的 trace.json 是通用格式,但方法名解析严重依赖 PDB 文件和路径匹配。生产环境部署若未保留符号文件或路径变更,就会丢失上下文。
- 转换前确认当前目录存在与 trace 对应的
.pdb文件,且文件名与 trace 中记录的模块名一致(如MyApp.dll对应MyApp.pdb) - 若 trace 来自另一台机器,需把 PDB 复制到本地,并用
dotnet trace convert --symbols-dir ./symbols显式指定符号路径 - Chrome://tracing 中搜索方法名失败,优先检查 “Process Name” 列是否显示为
dotnet而非你的应用名——这说明 Provider 没正确识别托管代码,大概率是没启用Microsoft-Windows-DotNETRuntime - 别指望
trace.json显示 IL 或 JIT 汇编;它只还原托管调用栈。要看汇编级细节,得用PerfView打开原始trace.nettrace并启用 “View > Show Assembly”
真正难的不是采集,而是判断该开哪些 Provider、该信哪一列时间(Exclusive vs Inclusive)、以及怎么把一堆线程堆栈和 GC 暂停时间拼成一个可行动的优化结论。这些没法靠工具自动完成,得结合你代码里那几个关键 async 方法和 lock 块的位置来交叉验证。











