Yafei Chang
Yafei Chang

Reputation: 105

Will gc collect the objects while the array set to nil in Golang?

I have an array that holds many objects. When I set the array to nil, will gc collect all the objects holded by the array?

package main

import (
    "time"
    "runtime"
)

type B struct {
    bb []int
}

func NewB() *B {
    return new(B)
}

func main()  {
    var bs = make([]*B, 10)
    for i:=0; i<10; i++ {
        bs[i] = NewB()
        bs[i].bb = make([]int, 1000000)
    }

    time.Sleep(time.Second)
    println("begin gc")
    //for i:=0; i<10; i++ {
    //  bs[i] = nil
    //}
    bs = nil
    runtime.GC()
    time.Sleep(time.Second*2)
    runtime.GC()
    time.Sleep(time.Second*2)
}

First, I set bs = nil, all the two gc infos show 76->76->76 MB, this means gc does not free the memory. Then, I add the for loop code in the slash statement, the first gc info shows 76->76->0 MB, the second gc info shows 0->0->0 MB. So I'm confused that, when I set bs = nil, there is no pointer referenced to all the objects, why gc does not free the objects? should all the objects explicitly set to nil?

Upvotes: 2

Views: 1746

Answers (1)

superfell
superfell

Reputation: 19040

If you compile with escape analysis turned on you'll see that bs doesn't escape and so is allocated on the stack, not the heap

go run -gcflags '-m -l' gc.go
# command-line-arguments
./gc.go:13:12: new(B) escapes to heap
./gc.go:20:18: make([]int, 1000000) escapes to heap
./gc.go:17:15: main make([]*B, 10) does not escape

so although you've nil'd bs the slice that bs was pointing to is still considered live by the gc by virtue of being on the stack. If you push your code down into its own func, and then GC after it returns, you'll see that the GC does reclaim all the memory.

func main() {
    alloc()
    runtime.GC()
    time.Sleep(time.Second * 2)
}

func alloc() {
    var bs = make([]*B, 10)
    for i := 0; i < 10; i++ {
        bs[i] = NewB()
        bs[i].bb = make([]int, 1000000)
    }
    time.Sleep(time.Second)
    println("begin gc")
    bs = nil
    runtime.GC()
}



begin gc
gc 5 @1.003s 0%: 0.003+0.052+0.021 ms clock, 0.026+0/0.036/0.055+0.17 ms cpu, 76->76->76 MB, 137 MB goal, 8 P (forced)
gc 6 @1.003s 0%: 0.001+0.037+0.018 ms clock, 0.010+0/0.036/0.023+0.15 ms cpu, 76->76->0 MB, 152 MB goal, 8 P (forced)

Upvotes: 7

Related Questions