Closed gyuho closed 8 years ago
Your assignment of kvs
to nil
is pointless because kvs
is not used after the assignment.
Perhaps you think that this assignment to nil
has some effect on your program, such as allowing garbage to be collected. It does not. As soon as kvs
goes out of scope, its value becomes eligible for collection. There is no need to assign to nil
here.
I feel I have an instance of this.
The intention here is indeed to make the rather large map available for the garbage collector. This time end-of-scope is not the saviour, unless perhaps Go tracks lifetime within a function.
type T struct{} // but indeed something large
func() {
kvs := make(map[int64]T{})
// kvs is being filled and grows
lst := make([]T{}, 0, len(kvs))
for … := range kvs {…} // map to list
// forgo kvs -- this triggers ineffassign
kvs = nil
// save lst to disk (takes a long time)
wg := new(sync.WaitGroup)
wg.Add(2)
filestore.SaveAsXML(wg, lst, …)
filestore.SaveAsJSON(wg, list, …)
wg.Wait() // best effort, we don't care for errors
return
}
@wmark I believe Go does track variable lifetime within a function. But I'm not certain of that, you should measure. In any case, it should. You can also introduce a scope (just wrap some lines in a {}
block) to make the lifetime explicit.
Thanks for looking into this.
I do indeed am aware of and use custom scoping. Which comes at a cost you don't always want to pay, and not always is a non-overlapping non-awkward scoping possible.
As per the spec variable lifetime of above example ends when the function body ends; which makes kvs = nil
a sensible operation and not ineffective.
The spec talks about scopes, not lifetimes. Scopes restrict where identifiers can be used, whereas lifetimes determine when memory becomes garbage. Since the spec says nothing about lifetimes, it is up to the compiler writers to decide exactly how that works. I seem to recall them solving this exact issue some years ago, but I am unable to find it now.
I agree that assigning nil is the easiest way to explicitly say "I don't need this memory any more". But, as I said, it should be unnecessary.
In fact, I've now run some tests and verified my suspicion that the garbage collector does indeed mark memory as garbage as soon as possible, without unnecessarily waiting until the end of a scope. I urge you to do your own measurements if this matters to you.
I can confirm lifetime tracking within scopes is in in Go 1.11 (implemented in Go, not the GCC flavour).
Thanks, and apologies.
We assign
nil
tokvs
, which is already used in previous line. And the tool assumes it's a new assignment. Could you fix this?Thanks.