清理GC的.NET数据结构

时间:2011-06-20 15:28:07

标签: .net memory-management garbage-collection dispose

在不再需要数据结构时清理数据结构会有所不同吗?我并不是说处理一次性用品 - 这显然是必需的,但是,例如,清理字典,列表或其他结构以减少对象的引用次数。

当反馈较少时(GC图表更简单),它是否有助于GC更快地释放内存?

3 个答案:

答案 0 :(得分:4)

不,它没有。如果无法访问“父”对象,则无论如何都不会遍历其“子”引用,因此它们没有区别。

更重要的是,清理代码通常会分散真正的代码。为了帮助垃圾收集器,很少值得将变量显式设置为null等。 是值得做的次,但他们通常会建议您也许应该重构代码(例如,如果您将局部变量设置为null,则使用较小的方法,或者如果您设置的话,则创建较小的对象)实例变量为null)。

答案 1 :(得分:0)

有两种值得注意的情况,将设置为null将加速垃圾收集:

  1. 变量包含一个实际上永远不会再次使用的引用,但代码是这样的,编译器无法告诉它。请注意,在调试时,只要它们在范围内,变量就会保持不变,无论它们是否会被再次使用(除此之外,因为操作员可以通过将执行点设置为更早的位置来强制它们再次使用在当前范围内),但在发布版本中,编译器可能会放弃不会再次使用的变量(请注意,如果不小心,可能导致与Finalize相关的错误!)
  2. 如果第2代对象拥有对第0代对象的引用,则在存在完整的第2代集合之前,第0代对象将无法进行收集。这可能不会发生很长一段时间。清除引用将允许更快地收集第0代对象。
  3. 如果需要保持活动的对象有一个或多个包含不再使用的引用的字段,清除这些引用将有助于垃圾收集器。

除非您有理由相信其中一种情况可能存在,否则清除参考文件可能不会有所帮助。第一种情况似乎经常在调试中发生,但除非有理由相信编译器不会将变量识别为过时,否则不应该担心它。第二种情况可能发生在调试或生产过程中,但发生这种情况所需的具体情况并不常见。第三个是最值得担心的。当一个类包含一个对象引用数组以及一个“size”字段时,会出现一个常见的变化,该字段指示有多少数组元素是“有意义的”。有四种方法可以“清除”这种结构:

  1. 只需将size字段设置为零即可
  2. 将size字段设置为零,然后重新分配一个新的(可能更小的)数组,放弃旧的数组。
  3. 将size字段设置为零并清除阵列的所有元素。
  4. 将size字段设置为零,清除数组的所有元素,然后放弃数组并分配一个新数组

将size字段设置为零是“逻辑”清除数据结构的最快方法。但是,除非或者直到它重新填充了它所持有的项目,否则它将保留对废弃元素的引用。分配一个新阵列并放弃旧阵列将避免这个问题,但如果阵列已经存在一段时间,可能会导致上面提到的情况#2。清除阵列的所有元素但如果阵列不是特别大,则保持阵列本身可能是最好的方法。清除所有元素并放弃数组可能是最好的方法,如果数组很大并且数据结构不可能立即重新填充任何接近于它曾经拥有的元素数量的东西。

答案 2 :(得分:-1)

编辑:而不是删除帖子,正如我所承诺的那样,我已经检查了文本,而且在我离开工作之前我怀疑我错了。我很欣赏Skeet先生在论坛上没有直接称我为血腥白痴,尽管他可能想要。即使在阅读了我引用的文本之后,我也不确定这个想法在我的脑海中浮现在哪里,它对垃圾收集方案的工作方式有很好的描述。无论如何,我道歉并承认我的错误。乌鸦味道不好,但我从错误的方式中学到了:)

CLR为每个创建的对象保留一个索引器,并在执行过程中递增/递减。当对象引用计数变为零时,将调度该内存分配以进行垃圾回收。可以通过超出范围的对象,将对象设置为null或调用IDisposable接口成员来减少引用。后面实现了IDisposable为课程的目的是清理不属于POCO资源,或使用不清理自动例如文件句柄,数据库连接,网络流等,否则,系统资源当对象超出范围,将在下一个GC循环期间清除内存。