【问题标题】:Difference between background and concurrent garbage collection?后台垃圾回收和并发垃圾回收的区别?
【发布时间】:2010-04-06 08:57:24
【问题描述】:

我读到 .NET Framework 4 替换了当前的垃圾回收实现:

.NET Framework 4 提供 背景垃圾收集。这 功能替换并发垃圾 以前版本中的集合和 提供更好的性能。

this page 有一个解释它是如何工作的,但我不确定我是否理解它。

在实际应用中,这种新的 GC 实现有什么好处?它是一个可以用来推动从 3.5 或之前版本过渡到 4.0 的功能吗?

【问题讨论】:

    标签: garbage-collection .net-4.0


    【解决方案1】:

    在这里,Microsoft 使用名称“并发”和“背景”来描述它在 .NET 中使用的两个版本的 GC。在 .NET 世界中,“后台收集器”是对“并发收集器”的增强,因为它对收集器运行时应用程序线程可以做什么的限制较少。

    基本 GC 使用“stop-the-world”策略:应用线程从公共堆中分配内存块。当 GC 必须运行时(例如,分配了太多块,需要进行一些清理),所有应用(托管)线程停止。最后一个停止线程运行 GC,并在完成后解除所有其他线程的阻塞。 stop-the-world GC 实现起来很简单,但会导致用户可以感知到的暂停。

    Microsoft 的“并发 GC”是分代的:它仅对堆的有限部分(他们称之为“第 0 代和第 1 代”)使用 stop-the-world 策略。由于该部分仍然很小,因此暂停仍然很短(例如低于 50 毫秒),因此用户不会注意到它们。堆的其余部分由专用 GC 线程收集,该线程可以与应用线程并发运行(因此得名)。

    并发 GC 有一些限制。也就是说,有时 GC 线程必须承担对堆的某种排他性控制。在这种情况下,应用线程只能从小的线程特定区域分配块。有更大需求的线程很快就会发现主堆,此时主堆被 GC 线程锁定。然后分配线程必须阻塞,直到 GC 线程完成其锁堆阶段。这再次引起停顿。与 stop-the-world GC 相比,暂停更少,并且这些暂停不会影响所有线程。不过还是停了下来。

    “后台 GC”是一种增强型 GC,其中 GC 线程不需要锁定堆。这消除了上一段中描述的额外停顿;只在收集年轻代时保持有限的暂停(微软称之为“前台收集”)。

    注意:并发 GC 和后台 GC 存在“隐藏成本”。为了让这些 GC 正常运行,来自应用线程的内存访问必须以一些非常特定的方式完成,这对性能有轻微影响。此外,GC 线程可能会对缓存内存产生不利影响,从而间接降低性能。对于不需要用户交互的纯计算任务,stop-the-world 收集器平均而言可能会产生更好的性能(例如,20 小时的计算将在 19 小时内完成) .但这是一种边缘情况,在大多数情况下并发和后台 GC 更好。

    【讨论】:

    • 很好的解释.. 但是如果你坚持主流术语会更合适。托管线程/代码等适用吗?那是什么?
    • 应用线程是运行程序员编写的代码的线程(与隐藏的管理线程相反,如果有的话)。 “托管”线程是运行托管代码的线程(即不是用 C 或 C++ 编写的代码)。这主流术语。
    【解决方案2】:

    这里是真实世界的解释,没有含糊不清和过度夸大的自我重要性:

    在并发 GC 中,您可以在 GC 中进行分配,但您不允许在 GC 中启动另一个 GC。这反过来意味着您在 GC 中允许分配的最大值是您留在一个段上 的任何空间(当前在工作站模式下为 16 MB)减去已经在那里分配的任何空间)。

    后台模式的不同之处在于,您可以在完全后台 GC 中启动新的 GC(第 0+1 代),而这甚至允许您创建一个新的段在必要时分配。简而言之,之前您在一个段中分配所有可能发生的阻塞将不再发生。

    来自苔丝达曼! http://blogs.msdn.com/b/tess/archive/2009/05/29/background-garbage-collection-in-clr-4-0.aspx

    【讨论】:

    • 在非GC线程运行时,GC做了哪些操作?如果非 GC 线程在 GC 线程移动对象时尝试写入对象的成员,会发生什么?如果在 GC 线程移动对象时创建了对对象的引用,会发生什么?并行执行的简单操作是将释放或移动对象使用的内存清零。难道只是营销炒作,一切都是并行完成的就是memset(ptr, 0, freedSize)?
    • 我在评论后发现了这一点:“CLR 启动后台收集并恢复所有托管线程。后台线程标记内存中所有可访问的对象并暂停应用程序线程以进行扫描或压缩阶段。” devblogs.microsoft.com/premier-developer/…
    【解决方案3】:

    主要好处是减少了由于垃圾收集而导致的应用程序冻结,这本身可以被认为是一项重大改进。对于大多数应用程序来说,除非内存中有大量长寿命对象,否则这种差异不会很明显。

    此更改还使 .NET 在构建对时间敏感的应用程序(其中响应时间很重要)方面更加可行。极端的例子是汽车安全气囊——你不希望你的软件在需要充气时忙于垃圾收集。 4.0 中的更改减少了由于 GC 导致的冻结次数和长度,但并未完全消除它们。

    【讨论】:

      猜你喜欢
      • 2015-11-13
      • 2011-12-21
      • 2012-01-28
      • 2013-06-27
      • 2011-11-29
      • 2021-12-20
      • 2011-07-15
      • 2014-03-09
      • 2013-06-10
      相关资源
      最近更新 更多