DotTrace系列:1. 理解四大经典的诊断类型(上)
一:背景
1. 讲故事
在所有与 .NET相关的JetBrains产品中,我觉得 DotTrace 是最值得深入学习和研究的一款,个人觉得它的优点如下:
- 跨平台诊断 (Windows,Linux,MacOS)
- 兼容 dotnet-trace 产出的 nettrace。
- 优秀的可视化界面,尤其是 timeline 时间轴。
- 支持自我托管和代码的局部诊断。
在我的 .NET高级调试知识系列下,这是一款不可或缺的利器,话不多说,我们就从四大诊断类型来开聊吧。
二:四大诊断类型
1. Sampling 模式
如果你的程序出现了性能变慢,但你又不知道是哪里的变慢?不知道从何入手,这时候就可以使用 Sampling 模式,它是从应用程序的角度帮你宏观洞察程序的性能,相当于性能洞察的第一道关卡。
Sampling 模式默认 5~11ms 对各个线程栈进行采样,通过大量的样本就能通过 group by 的方式计算出每个函数的累计执行时间,这里有一个小细节,如果 函数执行时间<5ms 的话,肯定是捕获不到的,这个也能理解。
接下来我们写一个简单的矩阵运算,然后寻找耗时的函数,参考代码如下:
using System;
using System.Diagnostics;
namespace MatrixOperations
{
internal class Program
{
static void Main(string[] args)
{
const int baseSize = 1000;
const int iterations = 3;
for (int i = 0; i < iterations; i++)
{
int matrixSize = baseSize - (i * 100);
PerformMatrixMultiplication(matrixSize);
}
}
static void PerformMatrixMultiplication(int matrixSize)
{
Console.WriteLine($"\n=== 处理 {matrixSize}x{matrixSize} 矩阵 ===");
Console.WriteLine("创建随机矩阵...");
var matrixA = GenerateRandomMatrix(matrixSize, matrixSize);
var matrixB = GenerateRandomMatrix(matrixSize, matrixSize);
Console.WriteLine("执行矩阵乘法...");
var timer = Stopwatch.StartNew();
var resultMatrix = MultiplyMatrices(matrixA, matrixB);
timer.Stop();
Console.WriteLine($"运算完成,耗时: {timer.Elapsed.TotalSeconds:0.000} 秒");
DisplayMatrixPreview(resultMatrix);
}
static double[,] GenerateRandomMatrix(int rows, int cols)
{
var random = new Random();
var matrix = new double[rows, cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
matrix[i, j] = random.NextDouble() * 100;
}
}
return matrix;
}
static double[,] MultiplyMatrices(double[,] matrixA, double[,] matrixB)
{
int aRows = matrixA.GetLength(0);
int aCols = matrixA.GetLength(1);
int bCols = matrixB.GetLength(1);
if (matrixA.GetLength(1) != matrixB.GetLength(0))
throw new ArgumentException("矩阵维度不匹配");
var result = new double[aRows, bCols];
for (int i = 0; i < aRows; i++)
{
for (int j = 0; j < bCols; j++)
{
double sum = 0;
for (int k = 0; k < aCols; k++)
{
sum += matrixA[i, k] * matrixB[k, j];
}
result[i, j] = sum;
}
}
return result;
}
static void DisplayMatrixPreview(double[,] matrix, int previewSize = 3)
{
Console.WriteLine($"\n矩阵预览 (前{previewSize}x{previewSize}个元素):");
int rows = Math.Min(previewSize, matrix.GetLength(0));
int cols = Math.Min(previewSize, matrix.GetLength(1));
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
Console.Write($"{matrix[i, j],8:0.00} ");
}
Console.WriteLine();
}
}
}
}
打开 dottrace,选择 Sampling 模式,点击 Start 即可,截图如下:

程序在运行完之后,会自动退出,dottrace 会自动打开收集到的追踪文件,截图如下:

从卦中可以挖出如下信息:
- dottrace采样了 21s。
- 非托管层占 14s + 托管层占 7s
- MultiplyMatrices 吃了7s,相对其他方法来说最耗cpu
要想知道 MultiplyMatrices 为什么会吃 7s,这个就属于细节问题了,Sampling模式就无法告诉你答案了。
值得一提的是,Sampling 属于大粒度的性能跟踪,生成的采样文件很小,适合天级别的长期监控。
2. Tracing 模式
刚才我们从应用程序 角度做了一个宏观洞察,发现了可疑函数 MultiplyMatrices ,我相信你此时会非常感兴趣,这个方法为什么会吃那么多的时间???
这就是本节要谈到的 Tracing 模式,相比 Sampling,它是方法级别的洞察,你会看到方法的更多信息,比如:
- 方法的调用时间
- 方法的调用次数
有些人可能会好奇,方法的调用次数底层是怎么算出来的? 这个是得益于 coreclr 的 ICorProfilerCallback 通知机制,在进入方法和退出方法时,coreclr都会通知给注册的第三方(DotTrace),具体细节就不说了。
接下来修改为 Tracing 模式,重新执行程序,截图如下:

DotTrace 跟踪完成之后,会产生跟踪文件,然后用F5搜索目标函数MultiplyMatrices 。截图如下:

从卦中我们获得了更多的信息,比如发现有人对 MultiplyMatrices 方法做了三次调用,总计花费近 8s,平均下来每次call 近 3s,如果觉得单次 3s 还是有点长,接下来该如何继续下钻呢?
值得一提的是,Tracing 属于方法级作用域,生成的采样文件相对较大,适合小时级监控。
3. Line-by-Line 模式
刚才我们说到的 Tracing 属于一种方法级作用域,再往下走的话只能是 语句级了,它的底层主要借助了IL插桩技术,有一些像 harmony 的 transpiler,由于插入了大量的垃圾代码,会导致程序运行速度极度的下降,久久不能跟踪结束!所以在这种细粒度的场景下,更适合用代码实现局部跟踪,后续的文章会跟大家继续聊。
当我跟踪了100s后,停止跟踪,打开视图后,右键点击 MultiplyMatrices 方法查看源代码,截图如下:

从卦中可以清晰的看到,在我跟踪的100s周期内都是被MultiplyMatrices方法给吃掉了,从 命中次数 角度看,耗时都在三层的 for 循环中 O(N3)。其中第三层的 for 已执行了 10亿+ 次。。。
三:总结
DotTrace 是一款非常的可视化商业工具,非常适合程序突然变慢的场景分析。
作为JetBrains社区内容合作者,如有购买jetbrains的产品,可以用我的折扣码 HUANGXINCHENG,有25%的内部优惠哦。

DotTrace系列:1. 理解四大经典的诊断类型(上)的更多相关文章
- 老生常谈系列之Aop--Aop的经典应用之Spring的事务实现分析(三)
老生常谈系列之Aop--Aop的经典应用之Spring的事务实现分析(三) 前言 上一篇文章老生常谈系列之Aop--Aop的经典应用之Spring的事务实现分析(二)从三个问题导入,分析了Spring ...
- OpenStack实践系列⑦深入理解neutron和虚拟机
OpenStack实践系列⑦深入理解neutron和虚拟机 五.深入理解Neutron 5.1 虚拟机网卡和网桥 [root@node1 ~]# ifconfig brq65c11cc3-8e: fl ...
- 《Entity Framework 6 Recipes》中文翻译系列 (25) ------ 第五章 加载实体和导航属性之加载完整的对象图和派生类型上的导航属性
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-5 加载完整的对象图 问题 你有一个包含许多关联实体的模型,你想在一次查询中, ...
- C++ : 从栈和堆来理解C#中的值类型和引用类型
C++中并没有值类型和引用类型之说,标准变量或者自定义对象的存取默认是没有区别的.但如果深入地来看,就要了解C++中,管理数据的两大内存区域:栈和堆. 栈(stack)是类似于一个先进后出的抽屉.它的 ...
- 【ABAP系列】SAP ABAP 实现FTP的文件上传与下载
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 实现FTP的文 ...
- 【ABAP系列】SAP ABAP ALV里日期类型的F4帮助
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP ALV里日期类 ...
- vue 快速入门 系列 —— 使用 vue-cli 3 搭建一个项目(上)
其他章节请看: vue 快速入门 系列 使用 vue-cli 3 搭建一个项目(上) 前面我们已经学习了一个成熟的脚手架(vue-cli),笔者希望通过这个脚手架快速搭建系统(或项目).而展开搭建最好 ...
- 【一个idea】YesSql,一种在经典nosql数据库redis上实现SQL引擎的方案(我就要开历史的倒车)
公众号链接 最高级的红酒,一定要掺上雪碧才好喝. 基于这样的品味,我设计出了一套在经典nosql数据库redis上实现SQL引擎的方法.既然redis号称nosql,而我偏要把SQL加到redis上, ...
- K3S系列文章-使用AutoK3s在腾讯云上安装高可用K3S集群
开篇 <K3s 系列文章> <Rancher 系列文章> 方案 在腾讯云上安装 K3S 后续会在这套 K3S 集群上安装 Rancher 方案目标 高可用 3 台master ...
- JS核心系列:理解 new 的运行机制
和其他高级语言一样 javascript 中也有 new 运算符,我们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象. 但在 javascript 中,万物皆对象,为什么还要通过 ...
随机推荐
- FastAPI测试策略:参数解析单元测试
扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长 探索数千个预构建的 AI 应用,开启你的下一个伟大创意 第一章:核心测试方法论 1.1 三层测试体系架构 # 第一层:模型级测试 def ...
- SpringBoot前后端接口加解密--解决方案
开放接口 - 通信方式采用HTTP+JSON或消息中间件进行通信. - 调用接口之前需要使用登录鉴权接口获得token. - 当鉴权成功之后才能调用其他接口(携带Token). 登录接口: Code ...
- GPU CPU运算时间测试
GPU CPU运算时间测试 本文主要探讨GPU,CPU在做一些复杂运算的时间测试 实验任务 1.向量加法 两个相同维度的向量a,b做加法,分别测试GPU并行时间(包含数据拷贝时间),CPU串行时间. ...
- 请求的资源不支持 http 方法“GET”。
错误重现 js ajax调用一个ASP.NET MVC写的api时,一直出现错误信息请求的资源不支持 http 方法"GET". 错误原因 ASP.NET MVC中的MVC(Web ...
- 最爱lx-music的音源哪里去了?
最爱lx-music,让你满心喜欢,可是音源没有了,因为被投诉给全部关了. 公心作者增加了自定义源. 六音提供了音源,做了一件大善事.注意的是音源会一直初始化.那就下载适合的版本: 欣赏阿鲁阿卓如痴如 ...
- cursor的mcp服务器安装(nodejs,npx安装和uv工具安装)
一.前言: 1.近期MCP服务器非常火爆,作为LLM大模型的通用工具手脚,MCP可以帮助LLM大模型实现更好的功能.本人经常使用cursor来进行代码的编辑,正巧cursor在0.47版本之后,MCP ...
- 线程,yield()
一.定义:暂停当前正在执行的线程对象,并执行其他线程 yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会. 因此,使用yield()的目的是让相同优先级的 ...
- Windows开机执行bat脚本
1.编写好bat脚本 2.将脚本复制到: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
- K8S 部署 Deepseek 要 3 天?别逗了!Ollama+GPU Operator 1 小时搞定
最近一年我都在依赖大模型辅助工作,比如 DeepSeek.豆包.Qwen等等.线上大模型确实方便,敲几个字就能生成文案.写代码.做表格,极大提高了效率.但对于企业来说:公司内部数据敏感.使用外部大模型 ...
- 【记录】VScode|两种缩放快捷键的功能和开启方式(Ctrl+/-,Ctrl滚轮)
1 面板缩放 快捷键:Ctrl+'+'/'-'. 2 滚轮缩放字体 快捷键:Ctrl+滚轮 开启方式:如下图,打开设置,搜索zoom,勾选. 更多快捷键:Ctrl+K Ctrl+S打开快捷键设置(或左 ...