强制垃圾收集以确保GC以后不会检查相当大的对象是一个好主意吗?

时间:2012-07-19 14:08:13

标签: c# garbage-collection

我已经创建了服务器应用程序,它必须在开始侦听客户端之前处理一些数据(这是一个非常繁重的过程)。在结果中,它分配了永远不会被使用但只使用一次的内存(大约30MB)。

它会给我带来强制垃圾收集的好处吗?或者让GC做它的工作?

此外,我必须使用.NET 3.5,据我所知,垃圾收集将中断线程,这就是我强迫垃圾收集器的原因。

3 个答案:

答案 0 :(得分:4)

好的,垃圾收集仍然只是一种启发式方法,尝试做出最好的猜测一般,但有可能你有一个合法的声称在特定时间比在知道更好。

以一个拥有大量资产的游戏为例。当您切换到新区域时,会弹出一个加载屏幕并开始加载新数据,从而释放对旧数据的引用。它还没有被收集,因为你没有达到你的门槛,但你可能很快就会打到它,因为你开始每帧创建你的小矩阵来呈现你的游戏,然后你会得到一个(可能是明显的)当你卸载数百兆的数据并移动其他所有数据以压缩队列时,口吃。

现在你可以在新资产加载后强制收集,因为用户已经处于“空闲”模式,盯着你的进度条,他不会注意到这个小口吃,你的游戏整体看起来会更顺畅

真正的诀窍就是知道何时干涉,何时不干涉。如果有疑问,请不要 - 无论如何都要进行收集,并且更频繁地进行收集只会使您的应用程序看起来更像更多。你需要一些东西来“隐藏”它,就像一个长期的任务,用一个进度条锁定你的应用程序,以某种方式产生很多已确定的对象 - 真的是游戏加载屏幕是我唯一可以提出的,但是YMMV。 / p>

答案 1 :(得分:1)

托管语言的一部分原因是你(可能)不必担心垃圾收集。只有非常特殊的情况才能手动调用垃圾收集器,这几乎肯定不是其中之一。

你可以阅读一下GC背后的一些语义,以及使它快速而不是慢here的原因,这可能是很好的理论阅读,所以你知道发生了什么。

与此同时,针对您的具体问题,我认为您应该查看IDisposable界面。如果您有一个特定的对象很大并且您担心,在它上面实现IDisposable接口将允许您将工作包装在using语句中,这保证了对象将在您即时处理掉。完成它。在那个特定硬币的另一面,它保证了对那个大对象有一个活动的,打开的句柄,因此在使用语句结束之前,GC无法获取它。

这可能比尝试手动使用GC更好地解决您的问题,这是一个黑盒子,可以通过设计结束程序员。

答案 2 :(得分:0)

你没有说你如何分配30MB的内存,但这很重要。如果要分配非托管内存,GC不会知道它(尽管您可以使用方法GC.AddMemoryPressure来告诉它)。在这种情况下,您应该在处理非托管内存的类上实现IDisposable,并且在完成对象后应该显式调用Dispose。

如果要分配托管内存,只需让GC完成其工作,除非

  • 你碰巧知道,在你完成对象之后,你的活动总会暂停,
  • 您实际上已经观察到GC在以后的某个时间点导致性能问题的证据。