GC(Garbage Collection)在计算机科学中是一种自动的存储器管理机制。当一个计算机上的动态存储器不再需要时,就应该予以释放,以让出存储器,这种存储器资源管理,称为GC。GC可以让程序员减轻许多负担,也减少程序员犯错的机会。
简单地说,GC是在后台运行一个守护线程,它的作用是在监控各个对象的状态,识别并且丢弃不再使用的对象来释放和重用资源。
Go GC分为Mark和Sweep两大阶段。Mark阶段又分为三个步骤,其中两个会有STW,另一个会有延迟。
Mark阶段的三个步骤:
在gc开始时,必须执行的第一个动作是打开写屏障(Write Barrier)。写屏障的目的是允许垃圾收集器在垃圾收集期间维护堆上的数据完整性,因为垃圾收集器和应用程序将并发执行。
为了打开写屏障,必须停止每个goroutine。此动作通常非常快,平均在10到30微秒之内完成。
一旦写屏障打开,垃圾收集器就开始标记阶段。垃圾收集器所做的第一件事是占用25%CPU。垃圾收集器使用Goroutines进行垃圾收集工作,. 这意味着对于一个4线程的Go程序,一个P将专门用于垃圾收集工作。
垃圾收集器首先检查所有现goroutine的堆栈,以找到堆内存的根指针。然后收集器必须从那些根指针遍历堆内存图,标记可以回收的内存。
如果垃圾收集器确定需要减慢内存分配,原本运行应用程序Goroutines会协助标记工作。应用程序Goroutine成为Mark Assist(协助标记)中的时间长度与它申请的堆内存成正比。Mark Assist有助于更快地完成垃圾收集。
垃圾收集器的一个设计目标是减少对Mark Assists的需求。如果任何本次垃圾回收最终需要大量的Mark Assist才能完成工作,则垃圾收集器会提前开始下一个垃圾收集周期。这样做可以减少下一次垃圾收集所需的Mark Assist。
一旦并发标记阶段完成,下一个阶段就是标记终止。最终关闭写屏障,执行各种清理任务,并计算下一个垃圾回收周期的目标。一直处于循环中的goroutine也可能导致stw延长(类似mark setup的情况)。
Sweep(并发清理)
标记完成后,下一阶段执行并发清理。清理阶段用于回收标记阶段中标记出来的可回收的内存。当应用程序goroutine尝试在堆内存中分配新内存时,会触发该操作。清理导致的延迟和吞吐量降低被分散到每次内存分配时。
减少堆内存的分配是最好的优化方式。比如合理重复利用对象;避免string和byte[]之间的转化等。
优化努力的方向:
垃圾收集是一个很好的权衡,虽然有垃圾收集的成本,却降低了内存管理的难度。但是也不能完全依赖垃圾收集器,养成良好的内存分配习惯,有助于提高应用程序的性能和吞吐量。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。