【问题标题】:What could cause an Application to linearly grow in RAM Usage?什么可能导致应用程序的 RAM 使用量线性增长?
【发布时间】:2012-01-30 23:52:52
【问题描述】:

情况
我创造了一个怪物。 Applikentstein 是一个 RAM 杀手,我仍然无法非常清楚地理解它是如何以及为什么在设计上如此流氓。基本上,它是一个计算应用程序,可以为 N 个场景启动测试组合。每个测试都在一个专用线程中进行,包括读取大型二进制数据、处理它并将结果放入数据库。 数据在读取时首先被放入缓冲队列(~100MB),并在处理时从流中出列。在处理过程中,数据块被跟踪到数组中。在线程方面,我有一个包含 N 个工作人员的工作人员缓冲区队列,每次一个工作人员完成并死亡时,都会通过队列启动一个新工作人员。

如果我启动太多线程(“太多”取决于系统 RAM)会发生以下情况
问题是 RAM 使用斜率在某些时候并没有变平,它只是不断增长,然后不时下降(几个线程完成,GC 做家务),但是一旦启动新线程,它就会反弹随着时间的推移,回来,越来越高(可能在这里泄漏)

随着时间的推移,我问过this 一个问题,that 一个和this 另一个。 现在是我感觉的时候了,我了解的越多,我真正了解的就越少。 (叹气)

问题
现在,我想对 究竟 是如何在 .Net 下管理内存有一个清晰的解释/资源。
我知道有很多关于这个广泛主题的文学/博客文章。但是这个话题太大了,我真的不知道从哪里开始而不失去自己(以及我公司的宝贵时间)。我想保持专注和目标导向。

第二,当我试图在实验室条件下模拟/再现上面的陡坡(由 RAM'saurus Monster “自然”创建)时,“倾斜”出现了,以隔离这种行为并找到解决方法(即监控进程使用的内存并将其限制为总内存的 X%,方法是停止任何新线程的创建)。
为什么在实验室条件下(使用一些消耗内存的多线程循环)如此难以重现我的流氓程序似乎很容易做的事情(在任务管理器中将 RAM 放在膝盖上)? GC 似乎会定期清理原型中的内容,而我的应用程序似乎将很多引用的内容保留在 RAM 中。怎么会 ?

第三个令人费解的事情是缓存的工作方式:为什么 firefox 使用高达 1 Gb 的内存并使用缓存,而我的应用程序只是破坏了 RAM?是否有可能正在运行的线程大量/频繁地使用数据,因此它永远不会被缓存?

跟踪和线索
我已经使用了 VS 分析器并确定了一些瓶颈(大数组排序),使用了 GCRoot 和 WinDBG 控制台。每次我狙击更多漏洞并修复其中一些(或多或少,比如缺少事件取消订阅等等......)

我知道我对记忆的一些基本概念的理解仍然很差,这是事实。这就是为什么我在这里要求领导。我准备阅读明智的资源并了解更多信息,并遵循一些开明的建议。

【问题讨论】:

  • 你创建了多少线程?每个线程使用 1MB 堆栈空间。也在看大型对象堆计数器吗?也许您那里有泄漏和/或碎片。
  • @ChrisO 这取决于可用的 RAM。 N 通常在 10 到 50 之间
  • 您正在使用大量 RAM,因为您拥有的内存太多了。你有 5 GB 根本没有被使用,非常浪费:)
  • @HansPassant。嗨汉斯! (你是由 SOF 付钱来困扰论坛的吗 :-P) 是的,这实际上是一个 HPC。我正在对其进行大量计算,而 RAM 饱和的事实阻止了我尽可能高效地使用它。在这张快照之后的 30 00 万,RAM 已经满了,以至于挂掉了。
  • 下次等30分钟再做截图:P

标签: c# performance


【解决方案1】:

与其说是答案,不如说是观察:

有很多不同的事情会影响这一点,这并不好笑。您描述的系统听起来像是您需要检查/观察数百种不同的东西。

其中最重要的是要跟踪您遇到的每一个内存泄漏。哪个,你已经开始了,但我建议你只需要继续前进。

关于 Firefox 和“缓存”的注意事项。你说的是windows分页文件; windows控制这个。关于何时将数据分页到磁盘以释放 RAM,它有自己的规则。我建议这是一条红鲱鱼,你不想走那条路。数据被分页到磁盘的一个原因是缺乏使用。对于 Firefox 和其他应用程序,这很常见;根据您的描述,您的软件的行为并非如此。

我会调查你的循环有多紧凑,以及你是否给了 .net 运行时执行清理的机会。看起来它正在强制使用问题,所以这可能没问题。

无论哪种方式,我都不明白到底是什么问题。您提到该图是启动过多线程的结果。好吧,这是意料之中的。您启动的每个线程都会占用资源;启动大量它们本质上会使用大量资源......在某些时候,系统将无法启动更多,它会级联失败。

影响您的实验室和生产系统的一些问题:不同的补丁级别 windows/.net/etc、不同的操作系统(例如 2008 与 2008 R2 是一个巨大的差异)、不同的 CPU 和/或内存配置。你给的东西真的不知道。

为了重现事件,您需要具有完全匹配的硬件和软件。然后你需要相同的输入。如果其中任何一个关闭,那么您可能能够靠近。首先要做的是确保所有加载和输入都是相同的。这些很容易控制。然后开始播放。


轻微更新。我阅读了您列出的一些问题。

为了确定系统的最佳线程数,您必须在目标硬件/软件上进行分析。最好在系统本身上。这需要相当多的手才能达到这一点。使其自动化的唯一方法是拥有一个看门狗来测试事物的运行方式并根据故障率增加或减少线程。有点像现在许多发烧友电脑可以自动超频:不断加热直到东西融化;然后后退 1 位。

当然,如果某些百分比的线程超出您通常允许的范围,或者如果某些其他软件启动并占用资源,您仍然可能会遇到问题。


tldr;你必须在它要运行的机器上手动调整它。准备好经常重调。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2012-11-21
    • 2015-08-05
    相关资源
    最近更新 更多