1

好的,只是要清楚,我知道任务管理器从来不是监视程序内存消耗的好方法。现在我已经清空了空气.......NET 4.0中的GC不会影响任务管理器中的工作集

我已经使用了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内存,所以当我运行我的应用程序并增加我的内存使用量时,我仍然有免费的TONS,所以我推测它只是不在意减少它已分配的内容(如任务管理器),即使内存已被“收集”。当我在1GB RAM的机器上运行这个相同的操作时,我从来没有发现内存不足的例外情况,这表明我真的没有泄漏内存(Profiler也建议这么做)。

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

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

回答

0

您不能指望立即反映在进程内存中的托管堆的使用发生更改。 CLR本质上充当了代表应用程序的内存管理器,因此它根据需要分配和释放段。由于分配和释放细分是一项昂贵的操作,因此CLR会尝试优化此操作。它通常不会立即释放一个空白段,因为它可能用于服务新的托管分配。如果你想监视托管的内存使用情况,你应该依靠.NET特定的计数器。

+0

感谢您的回复。我理解并同意你的回答(并且着重试图说服别人,任务管理器从来不是衡量内存使用情况的准确方法)。无论如何,客户仍然在使用它。我的观点是,在3.5和之前的CLR中,我至少会看到任务管理器显示的可预测的波动。现在,内存会在预期时增加,但不会减少(除非我执行其他随机操作,否则内存不会减少)。我不是说这意味着我有泄漏。我只是想知道是否CLR 4中的某些内容会影响到这一点。 – Devin

+0

任务管理器适用于进程内存,但托管内存只是整个进程内存的一部分,CLR可以自由地执行任何所需操作,以优化进程分配/释放托管堆所需内存的方式。 –

+0

再说一次,好点,但我的问题是CLR 3.5和4.0之间是否会改变这种看法。我很想向客户解释托管内存的细微差别,但他们似乎并不在乎。但是,他们确实付钱给我们,我需要确保他们很高兴:) – Devin