gpt4 book ai didi

c# - 如何使用 IDisposable 修复内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 20:42:55 25 4
gpt4 key购买 nike

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

4-500 MB 本身并不重要。令人担忧的是有 8 种不同的服务。每个都是使用 SharpArch、NServiceBus、Windsor 和 NHibernate 构建的。我的感觉是其中一个导致问题。我担心的是,所有服务的总内存大约是 4 个演出中的 3.2 到 3.6 个演出内存。它还没有抛出 OutOfMemory 异常,但我想在传递时阻止它。我还使用了 dotTrace,它给了我一些信息,我只是不确定如何对这些信息采取行动

最佳答案

我首先关心的是确保您正在衡量相关的东西。 “内存”可能意味着很多不同的东西。耗尽虚拟内存空间和耗尽 RAM 之间存在巨大差异。页面文件抖动导致的性能问题与GC压力过大导致的性能问题之间存在巨大差异。

如果您不了解 RAM、虚拟内存、工作集和页面文件之间的关系,那么请先阅读一些内容,直到您了解所有这些内容。您提出问题的方式让我怀疑您认为虚拟内存和 RAM 是一回事。 他们当然不是。

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

  • 我有八个进程,每个进程消耗 5 亿字节的虚拟地址空间
  • 我有 40 亿字节的 RAM
  • 因此,我即将收到 OutOfMemory 异常

  • 这种三段论是完全无效的。这就是三段论:
  • 我有八夸脱冰淇淋
  • 我的冰箱里有九夸脱冰淇淋的空间
  • 因此,如果我再得到两夸脱冰淇淋,某些东西就会融化

  • 事实上,您在隔壁有一个完整的仓库大小的冷藏设施。请记住,RAM 只是一种方便快捷的方式,可以在您需要的地方(例如冰箱)附近存储东西。如果你有更多的东西需要存储,谁在乎你本地的空间是否用完了?你可以随时弹出隔壁,把你不经常使用的东西长期深度卡住——页面文件。这不太方便,但没有融化。

    当进程用完虚拟地址空间时,而不是当系统中的所有 RAM 都用完时,您会收到“内存不足”异常。当系统中的所有 RAM 都用完时,您不会收到错误消息,而是会获得糟糕的性能,因为操作系统将所有时间都花在从磁盘来回运行内容上。

    因此,无论如何,首先要了解您正在测量什么以及 Windows 中的内存是如何工作的。您实际上应该寻找的是:
  • 在 32 位系统上是否有任何进程有使用超过 20 亿字节的虚拟内存的危险?一个进程只能获得 2GB 的虚拟内存(不是 RAM,请记住,虚拟内存与 RAM 无关: 这就是为什么它被称为“虚拟”——它不是硬件 )在 win32 上可以通过用户代码;如果你尝试使用更多,你会得到一个 OOM。
  • 是否有任何进程试图分配一个巨大的虚拟内存块以致没有该大小的连续块可用?例如,您是否可能在单个数组中分配一千万字节的数据?再次,OOM。
  • 工作集——即,出于性能原因*需要在 RAM 中的进程的虚拟内存页——所有进程的虚拟内存页是否小于可用 RAM 量?如果没有,那么很快您就会受到打击,但不会出现 OOM。
  • 如果 RAM 开始短缺,您的页面文件是否足够大以处理可以调出到磁盘的虚拟内存页面?

  • 到目前为止,这些都与 .NET 无关。一旦您确实确定存在真正的问题——可能没有——然后开始根据真正的问题进行调查。使用内存分析器检查内存分配器和垃圾收集器正在做什么。看看是不是大对象堆里有巨大的块,或者是意外的无法收集的活对象的大图,或者什么。但要使用良好的工程原理:了解系统,使用工具调查实际的经验性能,试验变化并仔细衡量其结果。不要只是开始在几个类上随机使用魔术 IDisposable 接口(interface),并希望这样做可以使问题(如果有的话)消失。

    关于c# - 如何使用 IDisposable 修复内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3112011/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com