Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 10, 2022 02:19 pm GMT

Maps, Slices and the Go Garbage Collector

Image description

In this article, I am going to present you with some examples showing why you should be cautions regarding the operation of the garbage collector. The point of the article is to understand that the way you store pointers has a great impact on the performance of the garbage collector, especially when you are dealing with very large amounts of pointers.

The presented examples will use pointers, slices and maps, which are all native Go data types.

What is Garbage Collection?

Garbage collection is the process of freeing up memory space that is not being used. In other words, the garbage collector sees which objects are out of scope and cannot be referenced anymore, and frees the memory space they consume. This process happens in a concurrent way while a Go program is running and not before or after the execution of the program. According to the documentation of the Go garbage collection:

The GC runs concurrently with mutator threads, is type accurate(also known as precise). allows multiple GC threads 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.

Using a Slice

In this example we will use a slice to store a large amount of structures. Each structure stores two integer values. Follow the below mentioned Go code:

package mainimport "runtime"type data struct{  i,j int  }func main() {  var N = 40000000  var str []data  for i:=0;i<N;i++ {    value := i    str = append(str, data{value,value})  }  runtime.GC()  _ = str[0]}

The last statement (_ = str[0]) is used for preventing the garbage collector from garbage collecting the str variable too early, as it is not referenced or used outside of the for loop. The same technique will be used in the below three Go programs that follow. Apart from this important detail, a for loop is used for putting values into structures that are stored in the slice.

Using a Map with Pointers

In this, we are going to use a map for storing all our pointers as integers. The program contains the following Go code:

package mainimport "runtime"func main() {  var N = 40000000  myMap := make(map[int]*int)  for i:=0;i<N;i++ {    value := i    myMap[value] = &value  }  runtime.GC()  _ = myMap[0]}

The name of the map that stores the integer pointers is myMap. A for loop is used for putting the integer values into map.

Using a Map Without Pointers

In this we are going to use a map that stores plain values without pointers. The Go code is mentioned below:

package mainimport "runtime"func main() {  var N = 40000000  myMap := make(map[int]int)  for i:=0;i<N;i++ {    value := i    myMap[value] = value  }  runtime.GC()  _ = myMap[0]}

As before, a for loop is used for putting the integer values into the map.

Splitting the Map

The implementation of this section will split the map into a map of maps, which is also called sharding. The program of this section contains the following Go code:

package mainimport "runtime"func main() {  var N = 40000000  split := make([]map[int]int,200)  for i := range split{    split[i] = make(map[int]int)  }  for i:=0;i<N;i++ {    value := i    split[i%200][value] = value  }  runtime.GC()  _ = split[0][0]}

This time, we are using two for loops: one for loop for creating the hash of hashes and another one for storing the desired data in the hash of hashes.

Comparing the Performance of the Presented Techniques

As all four programs are using huge data structures, they are consuming large amounts of memory. Program that consumes lots of memory space trigger the Go garbage collector more often. So, in this section we are going to compare the performance of each one of these four implementations using time(1) command.

What will be important in this presented output is not the exact number but the time difference between the four different approaches. Here we go:

$ time go run 1_sliceGC.goreal    0m1.511suser    0m0.000ssys     0m0.015s$ time go run 2_mapStar.goreal    0m10.395suser    0m0.000ssys     0m0.015s$ time go run 3_mapNoStar.goreal    0m8.227suser    0m0.000ssys     0m0.015s$ time go run 4_mapSplit.goreal    0m8.028suser    0m0.000ssys     0m0.015s

So, it turns out that maps slow down the Go garbage collector whereas slices collaborate much better with it. It should be noted here that this is not a problem with maps but a result of the way the Go garbage collector works. However, unless you are dealing with maps that store huge amounts of data, this problem will not become evident in your programs.

my blog

Thanks for reading :)


Original Link: https://dev.to/mavensingh/maps-slices-and-the-go-garbage-collector-2308

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To