Search code examples
gomemory-managementmemory-leaksgarbage-collection

Range loop on a Go channel and garbage collection of the loop variable


Consider the following Go code:

type LargeStructWithNestings struct {...}
func generatorChnl() <-chan *LargeStructWithNestings { ... }

// code snippet
chnl := generatorChnl()
for entry := range chnl {    // line A
    doStuffWith(entry)
    entry = nil              // line B
}

Assuming that the channel produces values infrequently, and these are pointers to large structs, does line B above cause garbage collection of the memory pointed to by entry to occur any sooner than it would otherwise do? Or once the loop spins back to line A, does the previous location in memory pointed to by entry become eligible for garbage collection as soon as the next iteration blocks at line A?

The objective is to find a way to keep the resident set size trimmed if possible.


Solution

  • The for statement does not clear the loop variable between iterations. There is a single loop variable which is re-used in each iteration. So until a new value is received from the channel, it will hold the value last assigned to it.

    So yes, if receiving from chnl blocks for a "long" time, the loop variable entry will keep a "reference" to the last received (and assigned) item and thus preventing it from getting garbage collected.

    In practice this is rarely–if ever–an issue. Values from channel may be received "frequently", the received values may be "small", there may be other references too, and any combination of these.

    If in your specific case this is really an issue, you may clear the variable, but I've never encountered any example where it was needed.