我有一个.net应用程序似乎有内存泄漏问题。 .net服务开始大约100MB的内存,但在负载下它大约400-500MB。我的大多数类没有非托管资源,而且已经实现了IDisposable。所以我的问题是在我的课程帮助上打字IDisposable吗?
4-500 MB本身并不关心。关注的是有8种不同的服务。每个都是使用SharpArch,NServiceBus,Windsor和NHibernate构建的。我的感觉是,其中一个中的某些东西导致了问题。我担心的是,所有服务的总内存大约是3.2到3.6 GB的内存。它还没有抛出OutOfMemory异常,但是我想在传球时把它关掉。我也使用了dotTrace,它给了我一些信息,我只是不确定如何处理这些信息
答案 0 :(得分:17)
我首先要关注的是确保你测量相关的东西。 “记忆”可能意味着很多不同的东西。耗尽虚拟内存空间和耗尽RAM之间存在巨大的差异。抖动页面文件导致的性能问题与因创建过多GC压力而导致的性能问题之间存在巨大的差异。
如果您不了解RAM,虚拟内存,工作集和页面文件之间的关系,那么请先阅读一些内容,直到您了解所有内容为止。你提出这个问题的方式让我怀疑你相信虚拟内存和RAM是一回事。 他们当然不是。
我怀疑你正在做的算术是:
这个三段论完全无效。这就是三段论:
当进程耗尽虚拟地址空间时,会出现“内存不足”异常,而不会消耗系统中的所有RAM。当系统中的所有RAM都被消耗时,你不会收到错误,你会得到废话性能,因为操作系统正在花费所有时间从磁盘来回运行东西。
因此,无论如何,首先要了解您正在测量的内容以及Windows中的内存如何工作。你应该寻找的是:
是否有任何进程在32位系统上使用超过20亿字节的虚拟内存?一个进程只能获得2GB的虚拟内存(不是RAM,记住,虚拟内存与RAM无关:这就是为什么它在win32上被称为“虚拟” - 它不是硬件)可以解决按用户代码;如果你试图使用更多的东西,你会得到一个OOM。
是否有任何进程存在尝试分配大量虚拟内存的危险,以至于没有该大小的连续块空闲?例如,您是否可能在一个阵列中分配一千万字节的数据?再次,OOM。
是工作集 - 即出于性能原因需要在RAM中的进程的虚拟内存页 - 所有进程的小于RAM可用吗?如果没有,那么很快就会发生颠簸,但不是OOM。
如果RAM开始变短,您的页面文件是否足以处理可以分页到磁盘的虚拟内存页面?
到目前为止,这与.NET没有任何关系。一旦你确定存在真正的问题 - 可能没有 - 然后根据真正的问题开始调查。使用内存分析器检查内存分配器和垃圾收集器正在执行的操作。查看大对象堆中是否存在大块,或者是否存在无法收集的活动对象的意外大图或什么。但要运用良好的工程原理:了解系统,使用工具调查实际的经验性能,试验变化并仔细测量其结果。不要只是开始在几个类上随机地打上魔术IDisposable接口,并希望这样做会导致问题 - 如果有的话 - 消失。
答案 1 :(得分:15)
如果所有具有非托管资源的类都实现IDisposable
并且已经妥善处理(通过使用或尝试/最终),那么添加更多IDisposable
实现将无济于事。
第一个问题是你不知道为什么要泄漏。托管应用程序通常由于以下原因之一而泄漏
鉴于您问题中的信息,几乎可以肯定#2导致问题。您需要获取一个分析器或windbg来告诉您实际泄漏是什么以及哪些有根对象导致它。
以下是Rico的一篇很棒的文章,可以帮助您入门
答案 2 :(得分:5)
答案是,几乎肯定不是。您是否通过剖析服务来验证您实际上是否存在不应该存在的内存?
请记住,垃圾收集器可能不一定在需要之前释放内存,因此它分配400-500mb可能并不罕见。我担心的一点是,在[插入合理的一段时间]之后,它会进一步爬升并达到1Gb,即使它没有达到任何更高的负载水平。
答案 3 :(得分:4)
简短回答:不。
更长的答案:Noooooo。
我想你已经知道了 - 如果你没有,你就不会在需要它的类上“打耳光”IDisposable - IDisposable与GC无关。唯一真正重要的是你是否已经无条件地将Finalizers(〜classname)放在你的对象上 - 这将导致它们在获得GC之前在单线程终结器队列中备份,而不管它们是否包含非托管资源或不。
答案 4 :(得分:2)
衡量,衡量,衡量
如果您想减少应用的内存使用量,您需要先确定它的使用位置。
你可以通过在“私有字节,所有堆中的字节,大对象堆中的字节,gen 1,gen 2”等上添加一些perfmon计数器来获得一个粗略的想法。
如果您确定使用了过多的托管内存。您可以使用.Net memory profiler之类的工具或非常灵活但windbg + sos
的工具进一步细分用法一旦你孤立了你的记忆,你可以看看减少使用的策略,它可能就像用Cache替换Dictionary或添加字符串构建器一样简单。
这种解决方案不太可能在所有东西上洒上一点点。