2018.12.18
Jalex Chang
- Backend Engineer @ Umbo Computer Vision
- Taiwan Data Engineering Association Member
- Golang Taiwan Member
- Introduction to garbage collection (GC)
- Basic GC strategies
- Fundamental knowledge of Go
- Go GC - Concurrent Mark & Sweep Collector
- Discussions and future works
- Conclussion
References
[1] Go 1.11, https://github.com/golang/go/tree/dev.boringcrypto.go1.11
[2] R. L. Hudson, Getting to Go: The Journey of Go's Garbage Collector, https://blog.golang.org/ismmkeynote/
[3] H. Okada, Go GC, https://engineering.linecorp.com/en/blog/go-gc/
[4] G. Bikshandi, Garbage Collection, http://polaris.cs.uiuc.edu/~padua/cs426/cs426-15.pdf
[5] S. Ghemawat and P. Menage, TCMalloc : Thread-Caching Malloc, http://goog-perftools.sourceforge.net/doc/tcmalloc.html
In computer science, garbage collection (GC) is a form of automatic memory management. The garbage collector attempts to reclaim garbage, or memory occupied by objects that are no longer in use by the program. - Wikipedia
Pros
- Incremental GC without STW
- Reclaim immediately
- Easy to implementation
Cons
- Hard to handle reference cycles
- Inefficiency in maintenance
- Cache-unfriendly (high miss rate)
- No memory compaction
2-phase object tracking method
Pros
- Overcome reference cycles
Cons
- Need to STW during GC
- No memory compaction
black objects can not refer white ones
Pros
- Overcome reference cycles
- Concurrent garbage collector
- STW only for setting up and re-scan
Cons
- Write barriers are needed
- No memory compaction
- Lower throughput than mark and sweep
Most objects die young
- GC more frequently from young space
- Relocating old objects to the space where GC less frequently
Pros
- Reduce the cost for scanning all objects
- Memory compaction
Cons
- Write barriers are needed all the time
Go is a value-oriented language in C-like systems languages rather than reference-oriented language in most managed runtime languages.
//go:noinline
func f1() people {
p := &people{
name: "Jalex",
email: "jalex.cpc@gmail.com",
}
println("V1", p)
return *p
}
//go:noinline
func f2() *people {
p := people{
name: "Jalex",
email: "jalex.cpc@gmail.com",
}
println("V2", &p)
return &p
}
Where should p be allocated? Stack frame or heap?
- A mechanism to automatically decide whether a variable should be allocated on the heap or not in compile time.
- It tries to keep objects on stack as much as possible.
Based on TCMalloc (Thread-Caching Malloc) - Provided by Sanjay Ghemawat and Paul Menage in 2007
Concepts:
- Each thread in GO has its own local thread cache (in heap)
- There are 70 size classes of free lists for small objects in thread cache.
- Allocate small object in thread cache.
- Allocate larger object (>32KB) in page heap.
- Allocating objects in thread cache are lock-free
=> Improve memory allocation performance
- Deallocating objects in thread cache is light-weight (without GC until total size exceed 2MB)
- A span is split into the same size of chunks for one class
=> Minimize the fragmentation.
- A span is continuous pages => Improve the locality
GC Checking:
- Allocate a object which is larger than 32KB
- Call runtime.GC()
- Every 2 minutes
GC triggering condition:
- Current heap size > 2 x defaultHeapMinimum x GOGC / 100
defaultHeapMinimum: 4MB, GOGC:100 (set by runtime/debug.SetGCPercent)
- Simply said: 8MB in default
The GC runs concurrently with mutator threads, is type accurate (aka precise), allows multiple GC thread to run in parallel. It is a concurrent mark and sweep that uses a write barrier. It is non-generational and non-compacting. Allocation is done using size segregated per P allocation areas to minimize fragmentation while eliminating locks in the common case. - Go1.11
A 99%ile isolated GC latency service level objective
GC statistics in Twitter's servers (18 GB heap):
Go's GC strategies
- Use value-orient style to improve locality.
- Apply escape analysis to stick objects on stack frame.
- Use TCMalloc to achieve memory compaction and to reduce GC efforts.
- Use concurrent mark and sweep collector with 2 short STW
- Only use write barrier during GC to maintain overall performance
Go's GC pause time is amazingly low now (~0.5 ms).
So, GC is not a problem in GO, but your programming style is.