Будет ли gc собирать объекты, когда в Golang для массива установлено значение nil? - PullRequest
0 голосов
/ 07 июня 2018

У меня есть массив, который содержит много объектов.Когда я установлю для массива значение nil, gc соберет все объекты, содержащиеся в массиве?

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)
}

Сначала я установил bs = nil, все две информации gc показывают 76->76->76 MB, это означает, что gc делаетне освободить память.Затем я добавляю код цикла for в оператор косой черты, первая информация gc показывает 76->76->0 MB, вторая информация gc показывает 0->0->0 MB.Поэтому я запутался, что, когда я установил bs = nil, указатель, на который ссылаются все объекты, отсутствует, почему gc не освобождает объекты?должны ли все объекты явно иметь значение nil?

1 Ответ

0 голосов
/ 07 июня 2018

Если вы скомпилируете с включенным анализом escape, вы увидите, что bs не экранирует и поэтому размещается в стеке, а не в куче

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

, так что, хотя вы ничего не сделали bs срез, на который указывал bs, все еще считается gc активным благодаря наличию в стеке.Если вы поместите свой код в свой собственный функционал, а затем в GC после его возвращения, вы увидите, что GC действительно освобождает всю память.

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)
...