在我的工作中,我们正在讨论清理大量托管约 50-100MB 内存的不同方法。桌面上有两种方法(阅读:两名高级开发人员不能同意),并且没有经验的其余部分团队不确定哪种方法更可取,性能或可维护性。
正在收集的数据是许多小项目,大约 30000 个,其中又包含其他项目,所有对象都被管理。这些对象之间有很多引用,包括事件处理程序,但不包括外部对象。我们将这一大组对象和引用称为单个实体,称为 blob。
方法#1:确保对 blob 中对象的所有引用都被切断,并让 GC 处理 blob 和所有连接。
方法#2:在这些对象上实现 IDisposable 然后对这些对象调用 dispose 并设置对 Nothing 的引用并删除处理程序。
第二种方法背后的理论是因为较大的生命周期较长的对象需要更长的时间在 GC 中清理。因此,通过将大对象切成小块,垃圾收集器将更快地处理它们,从而提高性能。
所以我认为基本问题是:拆分大量相互关联的对象是否会优化垃圾收集的数据,还是将它们保持在一起并依靠垃圾收集算法为您处理数据更好?
我觉得这是一个预优化的情况,但我对 GC 的了解还不够,无法知道什么有助于或阻碍它。
编辑:需要强调的是,内存的“blob”不是单个大对象,而是许多单独分配的小对象。
如果有帮助,请提供更多背景信息。我们有“泄漏”,因为对象没有被 GCed。两种方法都解决了泄漏问题,但在这一点上,这是一个更合适的争论。
最佳答案
第二种方法是错误的 - 它假设实现 IDisposable
会影响垃圾收集器。
不幸的是, IDisposable 与垃圾回收无关 .纯粹是为了发布非托管 资源。听起来您的第二个高级开发人员正试图为了自己的利益而变得有点“太聪明”。
第一种方法应该没问题。一旦您停止引用“blob”,博客中的每个对象都将变得无根,并且应该被清理。这可能会在您释放引用后的某个不确定时间发生(除非您明确告诉 GC 进行收集,我不建议这样做)。将为您正确处理相互依赖关系。
假设从理论上讲,实现 IDisposable 并清理内部引用可以加快收集过程。如果有(小的)净 yield ,那么处理所有这些数据所花费的时间很可能会超过 GC 中的任何 yield ——而且它确实超出了您的业务关注范围。
但是,我怀疑它实际上会减慢整个垃圾收集器的速度,而不是加快速度。将数据集分解为许多对象不会帮助 GC 运行得更快——它仍然需要跟踪实时引用,在这种情况下没有什么不同。
关于.net - 分而治之大对象的 GC 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2512179/