不需要的垃圾收集
在 Andrew Troelsen 所著的《C# 2010 和 .NET 4 平台》一书中的标题“强制垃圾收集”中写道:
“再次强调,.NET 的全部目的垃圾收集器代表我们管理内存。但是,在一些非常罕见的情况下,使用 GC.Collect() 以编程方式强制进行垃圾收集可能会有所帮助,具体来说:
• 您的应用程序即将进入一个块。您不希望被可能的垃圾收集中断的代码。 ... “
但是停下来!是否存在不需要垃圾收集的情况?我从未见过/读过类似的东西(当然是因为我的开发经验很少)。如果在您的实践中您做过类似的事情,请分享。对我来说 的一点。
这是非常有趣
In a title "Forcing a Garbage Colection" from book "C# 2010 and the .NET 4 Platform" by Andrew Troelsen written:
"Again, the whole purpose of the .NET garbage collector is to manage memory on our behalf. However, in some very rare circumstances, it may be beneficial to programmatically force a garbage collection using GC.Collect(). Specifically:
• Your application is about to enter into a block of code that you don’t want interrupted by a possible garbage collection.
...
"
But stop! Is there a such case when Garbage Collection is undesirable? I never saw/read something like that (because of my little development experience of course). If while your practice you have done something like that, please share. For me it's very interesting point.
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,绝对存在垃圾收集不受欢迎的情况:当用户等待某些事情发生时,他们必须等待更长时间,因为代码在垃圾收集完成之前无法继续。
这就是 Troelsen 的观点:如果您有一个特定的点,您知道 GC 不会有问题并且可能能够收集大量垃圾,那么它那么激发它可能是一个好主意,以避免它在不太合适的时刻触发。
Yes, there's absolutely a case when garbage collection is undesirable: when a user is waiting for something to happen, and they have to wait longer because the code can't proceed until garbage collection has completed.
That's Troelsen's point: if you have a specific point where you know a GC isn't problematic and is likely to be able to collect significant amounts of garbage then it may be a good idea to provoke it then, to avoid it triggering at a less opportune moment.
我运营一个与食谱相关的网站,并在内存中存储大量食谱及其成分使用情况的图表。由于我采用这种信息快速访问的方式,因此在加载应用程序时,我必须将几千兆数据加载到内存中,然后才能将数据组织成非常优化的图表。我在堆上创建了大量的微小对象,一旦构建了图表,这些对象就变得无法访问。
这一切都是在 Web 应用程序加载时完成的,可能需要 4-5 秒的时间。执行此操作后,我会调用 GC.Collect(); 因为我宁愿现在重新声明所有内存,也不愿在垃圾收集器崩溃时在传入 HTTP 请求期间可能阻塞所有线程清理所有这些短命的物体。我还认为现在最好清理一下,因为此时堆的碎片可能较少,因为到目前为止我的应用程序还没有真正执行任何其他操作。延迟此操作可能会导致创建更多对象,并且当 GC 自动运行时需要更多地压缩堆。
除此之外,在我 12 年的 .NET 编程生涯中,我从未遇到过想要强制垃圾收集器运行的情况。
I run a recipe related website, and I store a massive graph of recipes and their ingredient usage in memory. Due to the way I pivot this information for quick access, I have to load several gigs of data into memory when the application loads before I can organize the data into a very optimized graph. I create a huge amount of tiny objects on the heap that, once the graph is built, become unreachable.
This is all done when the web application loads, and probably takes 4-5 seconds to do. After I do so, I call
GC.Collect();
because I'd rather re-claim all that memory now rather than potentially block all threads during an incoming HTTP request while the garbage collector is freaking out cleaning up all these short lived objects. I also figure it's better to clean up now since the heap is probably less fragmented at this time, since my app hasn't really done anything else so far. Delaying this might result in many more objects being created, and the heap needing to be compressed more when GC runs automatically.Other than that, in my 12 years of .NET programming, I've never come across a situation where I wanted to force the garbage collector to run.
建议您不要在代码中显式调用
Collect
。你能找到它有用的情况吗?其他人已经详细说明了一些,毫无疑问还有更多。不过,首先要明白的是,不要这样做。这是最后的手段,研究其他选项,了解 GC 的工作原理,查看代码受到的影响,遵循设计的最佳实践。
在错误的位置调用
Collect
会让你的性能变得更差。更糟糕的是,依赖它会让你的代码变得非常脆弱。调用Collect
有益或最终无害所需的罕见条件可以通过对代码进行简单更改而完全消除,这将导致意外的 OOM、性能缓慢等。The recommendation is that you should not explicitly call
Collect
in your code. Can you find circumstances where it's useful?Others have detailed some, and there are no doubt more. The first thing to understand though, is don't do it. It's a last resort, investigate other options, learn how GC works look at how your code is impacted, follow best practices for your designs.
Calling
Collect
at the wrong point will make your performance worse. Worse still, to rely on it makes your code very fragile. The rare conditions required to make a call toCollect
beneficial, or at last not harmful, can be utterly undone with a simple change to the code, which will result unexpected OOMs, sluggish performamnce and such.我在性能测量之前调用它,这样 GC 就不会伪造结果。
另一种情况是内存泄漏的单元测试:
除此之外,我没有遇到过它实际上有帮助的情况。
特别是在生产代码中,恕我直言,永远不应该找到
GC.Collect
。I call it before performance measurements so that the GC doesn't falsify the results.
Another situation are unit-tests testing for memory leaks:
Besides those, I did not encounter a situation in which it would actually be helpful.
Especially in production code,
GC.Collect
should never be found IMHO.这种情况非常罕见,但 GC 可能是一个相当昂贵的过程,因此如果有一个特定的部分对时间敏感,您不希望该部分被 GC 中断。
It would be very rare, but GC can be a moderately expensive process so if there's a particular section that's timing sensitive, you don't want that section interupted by GC.
一个非常可疑的论点(尽管如此,它被大量使用)。
Windows 不是实时操作系统。您的代码(线程/进程)始终可以被操作系统调度程序抢占。您无法保证对 CPU 的访问。
所以归结为:GC 运行的时间与时隙(约 20 毫秒)相比如何?
关于这方面的硬数据很少,我搜索了几次。
根据我自己的观察(非常非正式),第 0 代集合是 << 40 毫秒,通常要短得多。完整的第 2 代可能会运行约 100 毫秒,甚至可能更多。
因此,被 GC 中断的“风险”与被换成另一个进程的风险是同一数量级的。而后者是你无法控制的。
A very suspect argument (that is nevertheless used a lot).
Windows is not a Real Time OS. Your code (Thread/Process) can always be pre-empted by the OS scheduler. You do not have a guaranteed access to the CPU.
So it boils down to: how does the time for a GC-run compare to a time-slot (~ 20 ms) ?
There is very little hard data available about that, I searched a few times.
From my own observation (very informal), a gen-0 collection is < 40 ms, usually a lot less. A full gen-2 can run into ~100 ms, probably more.
So the 'risk' of being interrupted by the GC is of the same order of magnitude as being swapped out for another process. And you can't control the latter.