Go

Garbage Collection in Go

Garbage Collection in Go

 

Introduction

A Garbage collector is a design of automatic heap memory management, it attempts to free up the allocations that are no long needed while keeping the allocations that are still in use. It makes a programmer’s life easier, with GC, it helps to prevent bugs such as dangling pointer bugs, double free bugs, memory leaks etc. On the other hand, it consumes more CPU and introduces more latency.

In this article, we are going to talk about the process of garbage collection in Go, including the phase of GC, strategies and design. By understanding GC, a developer can make better decision on memory allocation and write better code.


Mark-Sweap

Mark-Sweap is a classical algorithms to implement a garbage collector. The process including a mark phase and a sweep phase.

  1. Mark Phase - Mark the survival objects starting from root objects

2. Sweep Phase - Loop over the objects and free up the unmarked objects

The garbage collection in Go is based on the idea of Mark-Sweep.


Stategies

1. Stop The World (STW)

A goroutine can update the object reference during the garbage collection. This can lead to a free up to a in used object. To prevent this case, we need to stop all the running goroutine(Stop the world) during GC. However, STW means all the goroutines are not working which will lead to a bad performance.

2. tri-color marking

In Go garbage collection, it uses tri-color marking algorithms. The algorithms marks all the objects into 3 colors - white, gray and black.
black color - active objects, those objects can be visited from root objects
gray color - active objects, a temporary state which will later be marked as black
white color - nonactive objects, the objects will later be free up

The algorithms is quite straight forward as belows

markAllRootObjetcsToGray()
for len(grayObjetcs) != 0:
    MarkOneGrayObjectsToBlack()
    MarkAllObjectsPointedByThatBlackedObjectToGray()
3. Write Barrier

As we mentions above, STW(stop the world) can lead to a bad performance. Write barrier is introduced to solved the problem, it ensures the invariant in tri-color marking. Hence, we can restart the goroutines after the write barrier is turned on.

1. Dijstra Write Barrier

writePointer(slot, ptr):
    shade(ptr)
    *slot = ptr

2. Yuasa Write Barrier

writePointer(slot, ptr)
    shade(*slot)
    *slot = ptr

Phase of Garbage Collection

There are 3 phases in Go garbage collection.
1. Mark Setup
2. Marking
3. Mark Termination
Let’s go through the phases one by one

Mark Setup

When a collection starts, the first activity that must be performed is turning on the Write Barrier. The purpose of the Write Barrier is to allow the collector to maintain data integrity on the heap during a collection since both the collector and application goroutines will be running concurrently.
In order to turn the Write Barrier on, every application goroutine running must be stopped. This activity is usually very quick, within 10 to 30 microseconds on average. That is, as long as the application goroutines are behaving properly.

Marking

Once the Write Barrier is turned on, the collector commences with the Marking phase. The first thing the collector does is take 25% of the available CPU capacity for itself. The collector uses Goroutines to do the collection work and needs the same P’s and M’s the application Goroutines use. This means for our 4 threaded Go program, one entire P will be dedicated to collection work.

If the collector determines that it needs to slow down allocations, it will recruit the application Goroutines to assist with the Marking work. This is called a Mark Assist. The amount of time any application Goroutine will be placed in a Mark Assist is proportional to the amount of data it’s adding to heap memory. One positive side effect of Mark Assist is that it helps to finish the collection faster.

Mark Termination

Once the Marking work is done, the next phase is Mark Termination. This is when the Write Barrier is turned off(STW again), various clean up tasks are performed, and the next collection goal is calculated. Goroutines that find themselves in a tight loop during the Marking phase can also cause Mark Termination STW latencies to be extended.


Conclusion

In this article, we only focus on the idea of Go garbage collection without actual implementation details. We can see that it is not free to allocate memory in Go, garbage collector takes time to do the memory release for us(although a programmer might not aware of it). As a programmer, we should use the allocation cleverly and put your faith and trust in the garbage collector to keep the heap healthy and your application running consistently.

comments powered by Disqus