Why Golang?
One, created at Google and growing rapidly now having around 90,000+ repositories. Go can be used for cloud and systems programming and extended to the game server development and handling text-processing problems.
Two, many big companies use Go for their projects, like Google, Dropbox, Soundcloud, Docker, Cloudflare, BBC etc.
Three, Go is fast to learn, develop, compile, deploy, run
Four, Golang is created with cloud computing in mind, which will arguably define the future of the tech world. It has built-in testing facilitates for testing your code.
Five, Go supports cross-compilation with lots of tutorials and instructions on how to do it best.
Last, Garbage collector
Overview of Memory Management in Go
Go supports automatic memory management, such as automatic memory allocation and automatic garbage collection, which avoids many lurking bugs.
Memory block is a continuous memory segment and memory blocks may have different sizes. In Go, memory block may host multiple value such as struct, array and Slice etc.
When Memory block is allocated in Golang?
Typically, a functional parameters and local variables are allocated on the stack. In Go dynamic memory block is allocated mainly using new and make. New allocates exact one memory block that is used to create struct type value, whereas, make creates more than one memory block and returns the reference, like a slice, map or channel value. The literal created with the make, supports built-in append function to extend memory if required.
Where Memory block is allocated?
A memory block created by calling new function may be allocated on heap or stacks whereas memory block created by make is allocated on heap.
Go uses OS function mmap similar to TCMalloc (Thread-Caching Malloc) to allocate memory in heap.
Go uses goroutine, which maintain a small stack (memory segment) act as memory pool for some memory blocks. The maximum stack size is 1 GB on 64-bit systems, and 250 MB on 32-bit systems, can be set by SetMaxStack function.
Go supports stacks just to make Go programs run more efficiently. Go compiler allocate all memory block on the heap can be used by multiple goroutines, so here garbage collector comes into the picture.
Flags like -gcflags -m use to analyze memory block. Also, we can view each package-level variable allocated on the heap, and the variable is referenced by an implicit pointer that is allocated on a global memory zone.
When Memory block is collected in Go?
- Package-level allocated memory variables will never be collected.
- Goroutine stack collected automatic (not by garbage collector) while exiting.
- The garbage collector (GC) collects only allocated memory in a heap only if is not referenced i.e. unused memory blocks.
N.B. To debug Go uses Stack() to stack trace of goroutines.
How Compiler detects unused memory block?
In Go, garbage collection (GC) works in two phases, the mark phase, and the sweep phase. GC uses the tri-color algorithm to analyze the use of memory blocks, visits all grey global and stack objects and mark them as black and this process repeats till the last grey object and in sweep phase memory blocks will be collected.
garbage collector
GC maintains a table for every allocated memory with a reference count. Once the count comes to ZERO the object in heap marked as grey. The objects of the black set are guaranteed to have no pointers to any object of the white set. However, an object of the white set can have a pointer to an object of the black set because this has no effect on the operation of the garbage collector. The objects of the grey set might have pointers to some objects of the white set. Finally, the objects of the white set are the candidates for garbage collection.
Garbage collector starts when a threshold is satisfied defined in environment variable GOGC. Using SetGCPercent (package runtime/debug) function GOGC can be set, default GOGC=100 and negative percentage disables garbage collection.
GCStats collect information about recent garbage collections through GetGCStats function.
When variable Escapes to the heap?
Here “escapes to the heap,” means it will be dynamically allocated on the heap at runtime, because it is passed to a function argument that escapes itself.
x1 is not escaped to the heap, as it is not passed to any function where x2 escapes to the heap.
Some cause variables escape to the heap:
- Pointers or values as an argument to the function.
- Sending pointers or values containing pointers to channels: AS compiler cannot determine when goroutine will receive the data on a channel and when can be free.
- Pointers in a slice: slice may be on the stack but the referenced data escapes to the heap.
- Arrays of slices: It may get reallocated because an append can exceed its capacity.
- Methods on an interface type: As the interface gets type and value at runtime.
Debugging In GO:
We can use below flags for debugging Go memory:
- go tool compile -S testigGC.go
- go build -gcflags ‘-m -m’ testigGC.go
Reference:
TCMaloc: http://goog-perftools.sourceforge.net/doc/tcmalloc.html
https://cmc.gitbook.io/go-internals/chapter-i-go-assembly
https://blog.cloudflare.com/how-stacks-are-handled-in-go/
Have more questions on GoLang Memory Management?