1

好的,为了清楚起见,我知道任务管理器从来都不是监控程序内存消耗的好方法。现在我已经清除了空气...

我已经使用 SciTech 的 .Net 内存分析器有一段时间了,但几乎只在我们应用程序的 .Net 3.5 版本上使用。通常,我会运行一个操作,收集基线快照,再次运行该操作并收集比较快照并从那里攻击泄漏。一般来说,任务管理器会模仿记忆的上升和下降(在一定的准确度范围内和一定的时间段内)。

在我们的 .net 4.0 应用程序中,我们的测试部门在执行一组特定操作(我将其称为操作 A)时报告了内存。在分析器中,我会看到活动字节的相当大的变化(通常表示泄漏)。如果我立即收集另一个快照,则会回收内存(无论我等待收集初始比较快照多长时间)。我认为终结器可能会卡住,所以我手动注入了以下调用:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

当我这样做时,我看不到分析器中的初始泄漏,但我在任务管理器中的工作集仍然高得离谱(操作 A 涉及加载图像)。我认为这个问题可能是一个卡住的终结器(当分析器收集它的快照时,SciTech 能够做一些巫术魔法),但是在我使用 WinDbg 和 MDbg 所花费的所有时间里,我找不到任何暗示终结器卡住了。如果我只是让我的应用程序坐几个小时,工作集中的内存将永远不会减少。但是,如果我继续执行其他操作,内存将在随机点大幅下降。

我的问题 我知道 GC 在 CLR 4.0 中发生了很大变化,但它是否影响操作系统查看分配内存的方式?我的电脑有 12 GB RAM,所以当我运行我的应用程序并增加内存使用时,我仍然有 TONS 空闲,所以我假设它只是不关心减少它已经分配的内容(如任务管理器中所述),即使内存已被“收集”。当我在具有 1GB RAM 的机器上运行相同的操作时,我从来没有遇到内存不足的异常,这表明我真的没有泄漏内存(这也是分析器所建议的)。

我关心任务管理器显示的唯一原因是因为我们的客户如何监控我们的内存使用情况。如果 GC 发生变化会影响到这一点,我只想向他们展示说明这是 Microsoft 的错,而不是我们的错的文档 :)

在我的尽职调查中,我搜索了一堆其他 SO 线程来寻找答案,但我发现的只是关于分代清理的并发性和其他不相关但有用的事实的文章。

4

1 回答 1

0

您不能期望看到托管堆使用的变化会立即反映在进程内存中。CLR 本质上代表您的应用程序充当内存管理器,因此它根据需要分配和释放段。由于分配和释放段是一项昂贵的操作,CLR 试图对此进行优化。它通常不会立即释放空段,因为它可以用于提供新的托管分配。如果要监视托管内存使用情况,则应依赖 .NET 特定的计数器。

于 2012-10-12T01:00:16.673 回答