Thank you Ian for the great answer. 在2021年11月4日星期四 UTC+8 上午7:21:57<Ian Lance Taylor> 写道:
> On Wed, Nov 3, 2021 at 8:56 AM Ge <everg...@gmail.com> wrote: > > > > Hi, recently I was trying to figure out how GC marks stack objects and > found > > some places of the implementation detail over my head. > > > > source: > > ``` > > package main > > > > import "runtime" > > > > func main() { > > x := make([]byte, 256*1024*1024) > > runtime.GC() ← t1 > > x[0] = 2 > > > > runtime.GC() ← t2 > > println("x released") > > runtime.GC() > > println("over") > > } > > ``` > > > > The GC trace info was like this: > > ``` > > ➜ gc GODEBUG=gctrace=1 ./largeslice > > gc 1 @0.009s 0%: 0.051+0.27+0.005 ms clock, 0.40+0/0.18/0.034+0.040 ms > cpu, 256->256->256 MB, 257 MB goal, 8 P (forced) > > gc 2 @0.010s 1%: 0.033+0.21+0.004 ms clock, 0.26+0/0.16/0.078+0.032 ms > cpu, 256->256->256 MB, 512 MB goal, 8 P (forced) > > gc 3 @0.012s 1%: 0.019+0.091+0.003 ms clock, 0.15+0/0.15/0.047+0.024 ms > cpu, 256->256->0 MB, 512 MB goal, 8 P (forced) > > x released > > gc 4 @0.013s 1%: 0.014+0.11+0.004 ms clock, 0.11+0/0.13/0.058+0.036 ms > cpu, 0->0->0 MB, 4 MB goal, 8 P (forced) > > over > > ``` > > It seems that the slice x could be garbage collected after the last use > of it, > > which feels so intelligent and a little confusing, since fucntion call > did't return yet, > > and made me wondering how Golang dynamically identify these stack > objects. > > > > ``` > > // https://github.com/golang/go/blob/master/src/runtime/stack.go#L1246 > > func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) > (locals, args bitvector, objs []stackObjectRecord) { > > ... > > stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps)) > > ... > > ``` > > > > AFAIK stack pointer maps are got via getStackmap function, which > > reads FUNCDATA info from gopclntab(not very sure about this) section. > > > > My question is that will GC get different stack maps at t1 and t2 ? > > And if so how Golang implemented it, as GC stack scanning could happen > > at any time, which means for different pc there maybe lot of possiblites > > of stack maps. > > Yes, the GC will see a different map of live pointers on the stack at t1 > and t2. > > A GC can occur at any point where a goroutine can be preempted. That > means that the live pointer map has to be conservatively correct at > all such points. I say conservatively correct because while it is > essential that any live pointer be in the stack map, it is OK if a > previously live pointer remains in the stack map even after it is no > longer live. That will mean that the value stays live longer than > necessary, but it otherwise doesn't matter. In practice the compiler > builds stack maps that are correct at each function call. You can see > the livemaps generated by the compiler if you build with > -gcflags=-live=1. > > Ian > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/4790afc1-6dc2-4dee-abb9-61d2c67849b9n%40googlegroups.com.