如何使用IDisposable来修复内存泄漏 [英] How to use IDisposable to fix memory leaks

查看:240
本文介绍了如何使用IDisposable来修复内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个似乎有内存泄漏问题的.net应用程序。 .net服务开始大约有100MB的内存,但是在负载下它会达到大约400-500MB。我的大多数类没有非托管资源,并且已经实现了IDisposable。所以我的问题是将IDisposable打在我的课程帮助?



4-500 MB本身并不关心。关注的是有8种不同的服务。每个都使用SharpArch,NServiceBus,Windsor和NHibernate构建。我的感觉是,其中有一件导致问题。我担心的是,所有服务的总内存在4个演出中大约为3.2到3.6个内存。它并没有抛出OutOfMemory异常,但是我想在通关时关闭它。我也使用了dotTrace,它给了我一些信息,我只是不知道如何处理这些信息。

我首先关心的是确保你正在测量相关的东西。 记忆可能意味着很多不同的事情。虚拟内存空间耗尽和RAM耗尽之间存在巨大的差异。在颠覆页面文件导致的性能问题和创建太多GC压力导致的性能问题之间存在巨大差异。



如果你不明白RAM,虚拟内存,工作集和页面文件之间的关系,然后开始阅读,直到你理解了所有的东西。你说这个问题的方式让我怀疑你相信虚拟内存和RAM是同一件事。 他们当然不是。



我怀疑你正在做的算法是:


  • 我有8个进程,每个进程消耗5亿字节的虚拟地址空间

  • 我有40亿字节的RAM

  • 因此,我即将得到一个OutOfMemory异常



这个三段论是完全无效的。这是三段论:




  • 我有八夸脱的冰淇淋我有九个夸脱的空间冰淇淋在冰柜中的含量
  • 因此,如果我再加两夸脱的冰淇淋,就会有一些东西融化在一起b


    实际上你隔壁有一个仓库大小的冷库。请记住,RAM只是一种方便快捷的方式,可以将物料存储在您需要的地方,如冰箱。如果你有更多的东西需要存储,谁在乎你是否在本地用完了房间?您可以随时弹出隔壁,将您使用频率较低的内容放入长时间的深度冻结中 - 页面文件。

    当进程运行时,会出现内存不足超出虚拟地址空间,而不是当系统中的所有RAM都被占用时。当系统中的所有RAM都被占用时,你不会收到错误,你会得到糟糕的性能,因为操作系统正在花费所有时间来自磁盘来回运行。



    因此,无论如何,首先了解您正在测量的内容以及Windows的内存工作方式。实际上你应该寻找的是:


    • 任何进程都有可能使用超过20亿字节的虚拟内存一个32位系统?一个进程只获得2GB的虚拟内存(不是RAM,请记住,虚拟内存与RAM无关:这就是为什么称为虚拟 - 它不是硬件)在win32上是可寻址的由用户代码;如果您尝试使用更多内存,您将得到一个OOM。


    • 是否有任何进程试图分配大块虚拟内存,没有连续的大小的块是免费的?例如,您是否可能在单个阵列中分配千万字节的数据?再次,OOM。


    • 是工作集 - 也就是进程的虚拟内存页面,出于性能原因,RAM中的所有进程都小于可用RAM的数量?如果没有,那么很快就会出现颠簸,但不会是OOM。

    • 您的页面文件是否足够大以处理可以分页的虚拟内存页面如果RAM开始变短,那么到磁盘上? b
      到目前为止,这与.NET没有任何关系。一旦你确定存在真正的问题 - 可能没有 - 然后根据真正的问题开始调查。使用内存分析器来检查内存分配器和垃圾收集器在做什么。查看大对象堆中是否有巨大的块,或者意想不到的活动对象的大图,这些图不能被收集,或者是什么。但要运用良好的工程原则:理解系统,使用工具来调查实际的经验表现,试验变化并仔细测量其结果。不要只是开始在几个课堂上随机捣毁魔术IDisposable接口,并希望这样做会使问题 - 如果有的话 - 就会消失。


      I have an .net app that seems to have a memory leak issue(s). The .net service starts out around 100MB of memory, but under load it hits around 400-500MB. Most of my classes don't have unmanaged resources, and the ones that do already implement IDisposable. So my question is would slapping IDisposable on my classes help?

      The 4-500 MB isn't itself concerning. The concern is there are 8 different services. Each is built using SharpArch, NServiceBus, Windsor, and NHibernate. My feeling is that there is something in one of these that is causing a problem. My concern is that the total memory of all the services is around 3.2 to 3.6 gigs of memory out of 4 gigs. It is not throwing OutOfMemory exceptions yet, but I'd like to head this off at the pass. Also I've used dotTrace, which give me some information, I'm just not sure how to act on that information

      解决方案

      My first concern would be to ensure that you are measuring something relevant. "Memory" can mean a lot of different things. There is an enormous difference between running out of virtual memory space and running out of RAM. There is an enormous difference between a performance problem caused by thrashing the page file and a performance problem caused by creating too much GC pressure.

      If you don't understand what the relationships are between RAM, virtual memory, working set and the page file then start by doing some reading until you understand all that stuff. The way you phrased the question leads me to suspect that you believe that virtual memory and RAM are the same thing. They certainly are not.

      I suspect that the arithmetic you are doing is:

      • I have eight processes that each consume 500 million bytes of virtual address space
      • I have four billion bytes of RAM
      • Therefore I am about to get an OutOfMemory exception

      That syllogism is completely invalid. That's the syllogism:

      • I have eight quarts of ice cream
      • I have room for nine quarts of ice cream in the freezer
      • Therefore if I get two more quarts of ice cream, something is going to melt

      when in fact you have an entire warehouse-sized cold storage facility next door. Remember, RAM is just a convenient fast way to store stuff near where you need it, like your fridge. If you have more stuff that needs to be stored, who cares if you run out of room locally? You can always pop next door and put the stuff you use less frequently in long term deep freeze -- the page file. That's less convenient, but nothing melts.

      You get an "out of memory" exception when a process runs out of virtual address space, not when all the RAM in the system is consumed. When all the RAM in the system is consumed, you don't get an error, you get crap performance because the operating system is spending all of its time running stuff back and forth from disk.

      So, anyway, start by understanding what you are measuring and how memory in Windows works. What you should actually be looking for is:

      • Is any process in danger of using more than two billion bytes of virtual memory on a 32 bit system? A process only gets 2GB of virtual memory (not RAM, remember, virtual memory has nothing to do with RAM: that's why its called "virtual" -- it isn't hardware) on win32 that is addressible by user code; you'll get an OOM if you try to use more.

      • Is any process in danger of attempting to allocate a huge block of virtual memory such that there is no contiguous block of that size free? Are you likely to be allocating ten million bytes of data in a single array, for example? Again, OOM.

      • Is the working set -- that is, the virtual memory pages of a process that are *required to be in RAM for performance reasons -- of all processes smaller than the amount of RAM available? If not, then soon you'll get thrashing, but not an OOM.

      • Is your page file big enough to handle the virtual memory pages that could be paged out to disk if RAM starts to get short?

      So far none of this has anything to do with .NET. Once you've actually determined that there is a real problem - there might not be - then start investigating based on what the real problem is. Use a memory profiler to examine what the memory allocator and garbage collector are doing. See if there are huge blocks in the large object heap, or unexpectedly big graphs of live objects that cannot be collected, or what. But use good engineering principles: understand the system, use tools to investigate the actual empirical performance, experiment with changes and carefully measure their results. Don't just start randomly slapping magic IDisposable interfaces on a few classes and hope that doing so makes the problem -- if there is one -- go away.

      这篇关于如何使用IDisposable来修复内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆