在显式调用 GC 之前,应用程序不会释放内存
我同时启动许多线程,每个线程将数据写入队列或从队列中读取数据;数据在处理并存储到数据库时逐渐出队。由于某种原因内存没有释放,尽管队列是空的,并且我确保数据读取器和数据处理器之间的所有事件订阅在线程结束时取消订阅。的数量squatted RAM恰好是由二进制读取器读取并放入队列的数据量。
为了隔离问题,我绕过了处理和数据库存储步骤。
为什么在所有线程完成后,RAM 仍然占用很长时间,直到我显式调用 GC.Collect()
或终止程序?我在队列清空后手动将其作废,同时也将读取数据的Binary Reader作废。我认为这足以让 GC 至少在几分钟后醒来并进行内务处理。
编辑: (删除后重新表述)问题: 简而言之,我总是被告知默认的 GC 行为可以正确管理内存,并且我几乎永远不会显式调用 GC 并让框架来完成这项工作。
我想知道为什么在这种情况下,仅当显式调用 GC.Collect 时,内存使用率才会下降
编辑:
没有 GC Collect
使用 GC Collect(定期调用)
I am launching many threads simultaneously, each one writing / reading data into/from a queue; Data is dequeued progressively while it is processed and stored to DB. For some reason the memory is not freed although the Queues are empty and I made sure all event subscription between the data reader and the data processor are unsubscribed at the end of the threads.The amount of squatted RAM is Exactly the amount of the data that is read by binary readers and put into queues.
In order to isolate the problem, I have bypassed the Processing and the DB Storing step.
Why would be the RAM still squatted long after all threads are finished, until I explicitly call GC.Collect()
or terminate the program? I manually nullified the Queue after it is emptied, and also nullified the Binary Reader that read the data. I thought that would be enough for the GC to wake up and do its housekeeping at least after a few minutes.
EDIT :
The (reformulated after deletion) QUESTION :
In short, I was always told that the default GC behaviour managed the memory properly and that I shall almost never call the GC explicitly and let the framework do the job.
I would like to know why in this case memory usage drops down only when an explicit Call is made to GC.Collect
EDIT :
Without GC Collect
With GC Collect (Called on a regular basis)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在三种情况下可能会发生垃圾收集(请参阅 MSDN ):
从您的描述看来,框架决定既不是 1.) 也不是 2.) 的情况,因此它只会在您调用 GC.Collect() 时收集。
There are three conditions when a Garbage collection might occur (see MSDN):
From your description it sounds like the framework decided neither 1.) nor 2.) are the case hence it will only collect when you call
GC.Collect()
根据屏幕截图,在应用程序的整个运行过程中,您的内存使用量似乎从未超过 50%。对于 .NET 框架来说,保留该内存比停止应用程序(或至少占用大量 CPU 时间来检查活动性)来收集垃圾要快得多。如果您将机器的 RAM 削减到 2 GB 左右,我确信垃圾收集器会加强并将内存使用量保持在硬件限制内。
Based on the screenshot, it appears that your memory usage never goes over 50% during the entire run of the application. It's much faster for the .NET framework to leave that memory alone than to stop your application (or at least take up a lot of CPU time in checking for liveness) in order to collect the garbage. If you cut your machine's RAM to 2 GB or so, I'm sure that the garbage collector would step up and keep memory usage within the hardware limits.
看来您正在泄漏对象,您应该使用 Windbg 创建转储,然后使用 sos.dll 来跟踪对象的根。
您可以按照此关于如何跟踪对象的“根”并查看导致这些泄漏的原因的说明。
It seems you are leaking objects you should use windbg to create a dump then use sos.dll to track root for your objects.
You can follow this explanation on how to track "roots" for your objects and see what is causing these leaks.