关于Golang GC的一些误解,真的比Java算法更领先吗?
Go垃圾收集器的行为分为两个大阶段Mark(标记)阶段和Sweep(清理)阶段。Mark阶段又分为三个步骤,其中两个阶段会有STW(Stop The World),另一个阶段也会有延迟,从而导致应用程序延迟并降低吞吐量,这三个步骤是:
下面一一讨论。 Mark Setup阶段 垃圾收集开始时,必须执行的第一个动作是打开写屏障(Write Barrier)。写屏障的目的是允许垃圾收集器在垃圾收集期间维护堆上的数据完整性,因为垃圾收集器和应用程序将并发执行。 为了打开写屏障,必须停止每个goroutine。此动作通常非常快,平均在10到30微秒之内完成。 上图展示了在垃圾收集开始之前有四个goroutine在运行应用程序。为了暂停所有的goroutine,唯一的方法是让垃圾收集器观察并等待每个goroutine进行函数调用。等待函数调用是为了保证goroutine停止时处于安全点。如果其中一个goroutine不进行函数调用而其他goroutine执行函数调用,这种情况下会发生什么? 上图展示了一个问题。在P4上运行的goroutine停止之前,垃圾收集无法启动。然而由于P4处于如下循环中,垃圾收集器可能无法启动。
上面的代码片段是P4上正在执行的代码。go routine的运行时间取决于slice的大小。这段代码可以阻止垃圾收集器启动。更糟糕的是,当垃圾收集器等待P4时,其他P也无法提供服务。所以goroutines在合理的时间范围内进行函数调用对于GC来说是至关重要的。 Marking阶段 一旦写屏障打开,垃圾收集器就开始标记阶段。垃圾收集器所做的第一件事是占用25%CPU。垃圾收集器使用Goroutines进行垃圾收集工作,. 这意味着对于一个4线程的Go程序,一个P将专门用于垃圾收集工作。 (编辑:西安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |