dotTrace 2025.2 Help

基础。 分析类型

要成功使用 dotTrace,您需要对分析类型有一个良好的理解。 分析类型定义了在分析会话期间,dotTrace 将收集哪些应用程序数据以及收集的程度。 在配置分析会话时,您可以从以下分析类型中选择: samplingtracingline-by-linetimeline

采样

简要概述

dotTrace 会定期采集调用栈数据的样本。

优点:

  • 精确测量函数执行时间

  • 快照体积小

  • 非常轻量:内存使用量低;在分析器下运行应用程序所需的时间变化不大。

缺点:

  • 无法测量函数的调用次数

  • 并非所有调用栈和函数都会被捕获

  • 没有 ETW 事件、TPL 事件、本机函数的信息。

适用场景:

评估整体应用程序性能并找到最明显的性能瓶颈,即最慢的函数。

详细信息

采样是一种获取样本的过程或技术。 样本是分析会话期间采集的一组调用栈。 这引出了两个显而易见的问题: (1) 两个样本之间的间隔时间有多长(2) 获取一个样本需要多长时间。 这些问题的答案可以帮助我们估计采样方法的准确性。

dotTrace 会捕获进程中所有现有线程的调用栈,按顺序进行,无需暂停。 它还会考虑被锁定或处于休眠状态的线程。 捕获调用栈所需的时间无法精确确定,因为这取决于栈的深度以及本机和托管栈帧的数量。 因此,获取样本所需的时间必然会因样本而异,并取决于当前运行线程的数量。

dotTrace 在采集样本之间会有暂停。 暂停是指 dotTrace 停止处理前一个样本的线程活动后到开始处理下一个样本之前的时间。 每次暂停的长度是 5 到 11 毫秒之间的随机值。 随机值有助于降低调用栈中出现间隙的可能性。 在这些暂停期间,应用程序会正常运行。

其结果之一是,由于样本之间的时间至少为 5 毫秒,运行足够快的方法可能不会被捕获并显示在快照中。 然而,这并不会阻止 dotTrace 获取正确的时间数据。 可能存在两种情况。 如果一个方法运行得很快并且被多次调用,它将被捕获并显示在快照中。 如果一个方法运行得很快,但很少被调用,那么它可能会在快照中被忽略,但其时间将包含在其父方法的总时间中。 换句话说,如果一个方法的总时间显著,它将被计入。

总的来说,这种分析方法提供了有助于揭示问题调用栈的时间数据,但无法提供函数调用次数。 尽管如此,这种方法是最快的,可以作为定位性能问题的可靠第一步。

时间线

简要概述

dotTrace 记录应用程序事件并写入有关应用程序状态如何变化的数据。 基于 ETW 事件。 简而言之,结果是您获得了类似于采样分析的数据,但所有事件都显示在时间线上。

优点:

  • 精确测量函数执行时间。 函数调用显示在时间线上

  • 轻量级:在分析器下运行应用程序所需的时间变化不大

  • 提供 ETW 事件数据,例如内存分配、垃圾回收、I/O 操作等数据

  • 可以提供 TPL 数据:异步函数的 await 和 continuation 块

  • 可以在调用树中提供本机函数的数据(需要符号文件)

缺点:

  • 无法测量函数的调用次数

  • 并非所有调用栈和函数都会被捕获

  • 快照可能会非常大

适用场景:

  • 评估整体应用程序性能并找到最明显的性能瓶颈,即最慢的函数

  • 识别用户界面卡顿的原因

  • 识别过多的垃圾回收和 I/O 操作

  • 确定多线程应用程序中的问题,例如不规则的工作分配、锁争用、串行执行等

详细信息

时间线分析类型与采样分析非常接近。 两者都收集调用栈数据并允许确定性能瓶颈。 主要区别在于,在时间线分析期间,dotTrace 不会自行收集样本,而是从 Windows 事件跟踪 (ETW) 获取应用程序数据。

时间线分析的主要优势在于,它不仅允许您查看应用程序进行了哪些调用,还可以查看这些调用在时间上的分布。 这在分析多线程应用程序的行为时非常有用,因为事件的时间顺序确实很重要:例如,确定同步延迟、用户界面卡顿的原因等。

另一个优势是时间线分析收集了更广泛的数据。 除了调用栈数据外,它还记录了内存分配、垃圾回收和 I/O 事件。

跟踪

简要概述

每次特定函数被进入或离开时,CLR 都会通知 dotTrace。 dotTrace 测量这两个通知之间的时间。

优点:

  • 精确测量函数调用次数

  • 捕获所有调用栈和函数,内联函数除外

缺点:

  • 由于时间失真与函数调用次数之间的依赖关系,函数执行时间测量不准确

  • 重量级:在分析器下运行应用程序所需的时间更长;快照可能会非常大;内存使用量更高

  • 没有 ETW 事件、TPL 事件、本机函数的信息

适用场景:

评估算法复杂性,例如,当性能问题与频繁的函数调用相关时。

详细信息

与采样不同,跟踪围绕函数展开,更准确地说,是围绕函数的进入和退出。

dotTrace 从 CLR 接收通知,当一个函数被进入时以及当它被离开时,即使是由于异常而离开。 这两个通知之间的时间被视为函数的执行时间。

一方面,您可以在快照中获得所有未被 JIT 编译器内联且在该时间点执行的函数及其详细的时间数据。 另一方面,JIT 编译器为每个函数生成特定的序言和尾声,这需要 CLR 执行这些代码片段的额外时间。 dotTrace 不会计算并从函数总时间中减去这段时间。 因此,总时间可能会失真。 失真的程度取决于函数调用的次数。 这种依赖关系是线性的。 函数调用的次数越多,失真就越大。 函数执行的时间越短,其总时间的准确性可能越低。 例如,您有一个简单的函数 Inc() { _value++; } ,但它被调用了数百万次。 当然,它可以被优化,并且无论如何都会花费很少的时间。 然而,如果它在 dotTrace 下运行并选择了跟踪方法,每次调用此函数都会增加一些开销,这可能远远超过实际的函数执行时间。 因此,总时间可能会比使用采样方法或不使用分析器时更长。

CLR 可能会导致另一个开销。 CLR 提供了不同类型的优化。 根据 CLR 的版本和选择的分析方法,一些优化可能会被关闭或以不同的方式进行,因此结果可能会有所不同。

总体而言,您始终可以获得正确的函数调用次数,但函数的总时间可能不准确。 由于跟踪比采样花费更多时间,并且可能显著减慢您的应用程序,因此最好分析应用程序的单个部分或特定场景。

逐行

简要概述

dotTrace 测量每行代码的执行时间。

优点:

  • 可以详细研究一个函数

缺点:

  • 函数执行时间测量不准确

  • 极其重量级:与跟踪相比,在分析器下运行应用程序所需的时间更长;快照更大;内存使用量更高。

  • 没有 ETW 事件、TPL 事件、本机函数的信息。

  • 需要 PDB 文件

适用场景:

高级场景,例如,当您只想分析特定函数内部的性能时。

详细信息

此方法类似于跟踪,但这里的研究目标是语句,而不是函数。 为了逐行分析一个函数,dotTrace 需要 PDB 文件。 如果您没有相应的 PDB 文件,该方法的工作方式与跟踪相同。

dotTrace 测量执行 语句所需的时间以及它被执行的次数。 正如您可能想象的那样,这种方法比跟踪更慢,因为 dotTrace 对每个语句都执行时间计数工作。

逐行分析是一种有效的方法,适用于您已经缩小研究范围并希望专注于某些函数的情况。

最后修改日期: 2025年 9月 28日