Does go garbage collect parts of slices?

前端 未结 4 1316
名媛妹妹
名媛妹妹 2020-12-03 03:17

If I implement a queue like this...

package main

import(
    \"fmt\"
)

func PopFront(q *[]string) string {
    r := (*q)[0]
    *q = (*q)[1:len(*q)]
    re         


        
4条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-03 03:49

    Contrary to what I'm reading, Golang certainly seems to garbage collect at least unused slices starting sections. The following test case provides evidence.

    In the first case the slice is set to slice[:1] in each iteration. In the comparison case, it skips that step.

    The second case dwarfs the memory consumed in the first case. But why?

    func TestArrayShiftMem(t *testing.T) {
        slice := [][1024]byte{}
    
        mem := runtime.MemStats{}
        mem2 := runtime.MemStats{}
        runtime.GC()
        runtime.ReadMemStats(&mem)
    
        for i := 0; i < 1024*1024*1024*1024; i++ {
            slice = append(slice, [1024]byte{})
            slice = slice[1:]
            runtime.GC()
    
            if i%(1024) == 0 {
                runtime.ReadMemStats(&mem2)
                fmt.Println(mem2.HeapInuse - mem.HeapInuse)
                fmt.Println(mem2.StackInuse - mem.StackInuse)
                fmt.Println(mem2.HeapAlloc - mem.HeapAlloc)
    
            }
        }
    }
    
    
    func TestArrayShiftMem3(t *testing.T) {
        slice := [][1024]byte{}
    
        mem := runtime.MemStats{}
        mem2 := runtime.MemStats{}
        runtime.GC()
        runtime.ReadMemStats(&mem)
    
        for i := 0; i < 1024*1024*1024*1024; i++ {
            slice = append(slice, [1024]byte{})
            // slice = slice[1:]
            runtime.GC()
    
            if i%(1024) == 0 {
                runtime.ReadMemStats(&mem2)
                fmt.Println(mem2.HeapInuse - mem.HeapInuse)
                fmt.Println(mem2.StackInuse - mem.StackInuse)
                fmt.Println(mem2.HeapAlloc - mem.HeapAlloc)
    
            }
        }
    }
    

    Output Test1:

    go test -run=.Mem -v .
    ...
    0
    393216
    21472
    ^CFAIL  github.com/ds0nt/cs-mind-grind/arrays   1.931s
    

    Output Test3:

    go test -run=.Mem3 -v .
    ...
    19193856
    393216
    19213888
    ^CFAIL  github.com/ds0nt/cs-mind-grind/arrays   2.175s
    

    If you disable garbage collection on the first test, indeed memory skyrockets. The resulting code looks like this:

    func TestArrayShiftMem2(t *testing.T) {
        debug.SetGCPercent(-1)
    
        slice := [][1024]byte{}
    
        mem := runtime.MemStats{}
        mem2 := runtime.MemStats{}
        runtime.GC()
        runtime.ReadMemStats(&mem)
        // 1kb per
    
        for i := 0; i < 1024*1024*1024*1024; i++ {
            slice = append(slice, [1024]byte{})
            slice = slice[1:]
            // runtime.GC()
    
            if i%(1024) == 0 {
                fmt.Println("len, cap:", len(slice), cap(slice))
                runtime.ReadMemStats(&mem2)
                fmt.Println(mem2.HeapInuse - mem.HeapInuse)
                fmt.Println(mem2.StackInuse - mem.StackInuse)
                fmt.Println(mem2.HeapAlloc - mem.HeapAlloc)
    
            }
        }
    } 
    

提交回复
热议问题