0

我有一个非常简单的 GUI 应用程序,可以为系统运行 HIL 测试。我从组合框中选择一个测试,然后单击运行。这将启动测试并运行 27 分钟。在此期间,CPU 正在捕获数据并将数据存储在 String Builder 中。测试完成后,字符串生成器将捕获的数据写入文件。我运行了 3 次相同的测试来检查内存泄漏。请看附图。

快照#1:GUI 开始快照#19:第一次尝试结束快照#33:第二次尝试结束快照#38:第三次尝试结束

如果我们比较 33 和 38,我们可以看到对象和堆大小是相同的,这让我相信没有内存泄漏。

但是如果我们比较 19 和 33/38,我们可以看到对象数量增加了 1,堆大小增加了 0.1KB,这让我相信存在小的内存泄漏。

如果我们将 1 与其他比较,我们会看到对象的数量和堆大小相对而言增加了很多。

所以我的问题是,这里有内存泄漏吗?我如何得出一个可靠的结论?

快照

诊断会话1

诊断会话2

4

1 回答 1

0

C# 使用垃圾回收 (GC) 的概念,这意味着对象不会在作用域结束时被释放,而是在之后的某个任意时间,可以是几秒甚至几分钟。

在您的工具中,GC 运行由内存条顶部的黄色小勾号指示。

GC 刻度线

如您所见,大约在 37:00 左右(大约 2200 秒)发生了一次垃圾回收。

所以我的问题是,这里有内存泄漏吗?

目前数据太少,无法确定。

我如何得出一个可靠的结论?

  1. 您需要一个特定于.NET 的工具,即它知道.NET 是垃圾收集的,并且会在测量之前执行垃圾收集。例如 Jetbrains dotMemory(Resharper 的一部分)。

  2. 设置一切以进行测量

  3. 运行测试序列一次。这将确保加载 DLL,初始化静态内容,加载延迟加载内容等。

  4. 拍摄快照

  5. 运行测试序列 5 次(使用素数)

  6. 再拍一张

  7. 运行测试序列 7 次(使用素数)

  8. 分析快照之间的差异。

    任何泄漏通常在第一次运行期间泄漏 5 次,在第二次运行期间泄漏 7 次或多次。如果所有运行都相同,则几乎不能在 7 次运行中泄漏 2 个对象(可能会发生很多ifs;确保每次运行都执行相同的操作)。

    如果您有这样的泄漏,请进行代码审查以检查它将被释放的位置。

潜在的误报:

  • 缓存

  • 在整个测试序列中附加的日志文件或类似文件

注意:在 Visual Studio 中,不要只使用开始调试时自动运行的诊断工具。相反,使用 Debug / Performance Profiler 并选择“内存使用情况”

性能分析器内存使用情况

那个允许你强制 GC 并拍摄快照。

强制GC

于 2022-02-11T20:43:45.357 回答