ahfuzhang

https://github.com/ahfuzhang

导航

[DotNet] build 与 trace 时候的一些编译选项: 如何编译二进制程序才能使用 dotnet-trace 采集到 cpu profile

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


我希望 dotnet 可以像 golang 那么方便,用浏览器连接到 http 端口,就能进行 trace ,采集 cpu profile 数据,并展示火焰图。
一开始我打算自建一个在线 debug 的 all-in-one 镜像来解决这个问题:see https://github.com/ahfuzhang/CSharpDbgContainer

实际使用中发现,如果不使用 dotnet xxx.dll 或者 dotnet run --project xxx.csproj 的模式,如果直接编译为二进制,使用 dotnet-trace 就无法采集到 cpu profile 数据。
究竟哪几个参数影响了 dotnet-trace 采集数据?下面是我实验得到的结论:

dotnet publish MyProj.csproj \
			-c Release -r linux-x64 \
			-p:PublishAot=false \
			-p:StripSymbols=false \
			-p:EventSourceSupport=true \
			-p:PublishReadyToRun=true \
			--self-contained false \
			-o ./build/MyProj/linux/amd64/

重点是以下参数:

  • -p:EventSourceSupport=true 支持 dotnet 内部的 event 机制
  • -p:PublishReadyToRun=true 提前编译,启动/吞吐更接近“发布体验”,但仍然是 CoreCLR(JIT runtime),dotnet-trace cpu-sampling 这条链路通常能工作。
  • -p:PublishAot=false 关闭 Ahead-of-Time 功能
    • -p:PublishAot=true 的作用是:在 dotnet publish 时启用 Native AOT(Ahead-of-Time)发布,把你的 .NET 应用 提前编译成原生机器码的单文件可执行程序(native binary),运行时不再依赖 JIT 编译。也就是说,它走的是 “本机原生程序 + 精简运行时” 的部署形态,而不是传统的 CoreCLR/JIT 形态。

按照以上参数,就能在使用 dotnet-trace 的时候正确采集 cpu profile 数据

dotnet-trace 的命令行如下:

dotnet-trace collect --profile dotnet-sampled-thread-time --duration 00:00:${seconds} --format Speedscope -p ${processId} -o ${outputTracePath}

另外,推荐的参数是:

  • -p:StripSymbols=false 保留符号
  • --self-contained false 不拷贝系统的 dll,看起来清爽一些
  • -p:EmbedAllSources=true 把源码编译到符号中,便于调试

posted on 2026-02-26 10:53  ahfuzhang  阅读(14)  评论(0)    收藏  举报