dotMemory 2025.2 Help

分析概览

dotMemory:分析概览

完成收集分析数据后,dotMemory 会打开一个新选项卡,显示 分析概览 页面。

分析概览 页面为您提供会话期间收集的数据的信息:

时间线

时间线

时间线图显示了应用在分析过程中如何消耗内存。 时间线由四个图表组成,显示 Gen0、Gen1、Gen2 堆、大对象堆和固定对象堆的即时大小。 您还可以通过选择 显示非托管的内存 参数添加显示非托管内存大小的图表。

时间线图可以作为分析的良好起点:

  • 要查看特定时间点的确切内存堆值,请点击该时间点的时间线图。

  • 要查看某个时间间隔内分配的内存量,请在图表上选择所需的时间间隔。 要获取有关该时间间隔内分配的对象及分配这些对象的函数的详细信息,请点击 已分配:... MB 链接。 这将打开 内存分配 视图。

  • 如果您不确定从哪里开始,请查看实时检查的结果。 有关更多信息,请继续阅读。

实时检查

在分析过程中,dotMemory 会实时分析内存分配数据。 它使用这些数据自动检测潜在的内存分配问题:

当检测到问题时,dotMemory 会在时间线图顶部的列表中显示该问题。 要选择检测到问题的特定时间间隔,请在列表中选择该问题。

实时检查

Gen0 中的固定对象

在某些情况下,例如从托管代码中使用非托管代码(例如外部库)时,您的应用可能会分配所谓的 固定对象。 这些对象被“固定”在小对象堆中——它们无法在堆中移动,因为托管代码依赖于这些对象的确切位置。 这会导致一个负面后果——垃圾回收器无法压缩小对象堆。 这可能导致更频繁且效率较低的垃圾回收,从而降低整体应用性能。

例如,我们在 Gen0 中有以下对象布局: [A][B][Pinned][C][D]。 对象 [A][B][Pinned] 对象从堆中移除之前无法被回收。

dotMemory 能够自动检测托管堆 Gen0 段中固定对象的分配。

固定对象的可能来源:

  • 您可以使用 fixed 块有意创建固定对象:

    unsafe { var buffer = new byte[2000]; fixed (byte* ptr = buffer) { ... } }
  • 您创建了一个 GCHandle 到一个对象,从而防止它被垃圾回收:

    var buffer = new byte[2000]; var gCBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);

可能的解决方案:

  • 如果可能,请考虑使用 stackalloc 在栈上分配缓冲区,而不是在堆上:

    var buffer = stackalloc byte[2000];
  • 如果缓冲区包含固定对象,将其分配到大对象堆而不是小对象堆可能更为合理。 为此,请将缓冲区的大小设置为大于 84 KB。

高 GC 压力

高 GC 压力是指垃圾回收过于频繁并占用了大量时间的情况。 即,在某些采样的特定时间间隔内,垃圾回收所花费的时间超过了总执行时间的 30%。

典型原因:

  • 程序创建了大量短生命周期的对象,例如循环中的闭包。

  • 程序接近 Out of Memory

可能的解决方案是修改代码以防止频繁分配。 您可以在以下系列博客文章中找到更多此类问题的示例:

快速 LOH 增长率

大对象堆(LOH)是托管堆的一个特殊段,用于存储大对象(>84 KB)。 dotMemory 实时跟踪 LOH 的增长。 如果 LOH 增长过快,可能会导致严重的碎片化,并最终抛出 OutOfMemory 异常。

典型原因:

动态大小的集合(如 DictionaryListHashSetStringBuilder )具有以下特性:当集合大小超过当前边界时,.NET 会调整集合大小并在内存中重新定义整个集合。

可能的解决方案是减少需要调整大小的情况。 尝试预测所需大小,并以该大小或更大的值初始化集合。

已收集的快照

已收集的快照

此区域包含有关分析期间收集的所有快照的简短报告。 每个报告允许您:

  • 获取有关应用请求的 总计 内存量* 的详细信息。 总计 值(灰色条)包括:

    • 非托管内存:在托管堆外分配且不由垃圾回收器管理的内存。 通常,这是 .NET CLR、动态库、图形缓冲区等所需的内存。 这部分内存无法在分析器中进行分析。

      如果您清除 显示非托管的内存 复选框,非托管内存的大小将从 总计 值中减去。

    • .NET,总计 (带轮廓的灰色条):应用在托管堆中使用的内存量,包括分配对象之间的空闲空间。 请参见下图以获取更多信息。

    • .NET,已用 (深灰色条):应用在托管堆中使用的内存量,不包括空闲空间。 这是 .NET 允许您操作的唯一内存部分。

    内存使用情况
  • 通过点击快照名称,在 快照视图 中打开快照。

  • 使用 重命名 按钮重命名快照。

  • 打开堆中的所有对象进行分析(使用 [objects size] 对象 链接)。 在这种情况下,“所有对象”对象集将在 按类型分组 视图中打开。

  • 打开标记的对象进行分析(使用 标记的对象 链接)。 “标记的对象”对象集将在 类型 视图中打开。 在 标记实例 部分了解更多关于标记对象的信息。

  • 查看从分析会话开始到获取快照时应用生成的内存分配(使用 内存分配 链接)。 在 分析流量 部分了解更多关于分析内存分配的信息。

快照比较区域

要比较两个快照,请将它们拖动到 比较区域 ,或为每个快照点击 添加到比较。 在 比较快照 部分了解更多关于如何比较快照的信息。

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