runtime: types are not garbage collected
rogpeppe opened this issue · 5 comments
go version devel +644ddaa842 Wed Nov 7 16:12:02 2018 +0000 linux/amd64
Newly created types are not garbage collected, so code which creates types on the fly in response to runtime data can leak memory.
This code prints a large number when it should print zero: https://play.golang.org/p/R6N6IJSzYTD
Yep. This is a hard one to fix.
We depend on type uniqueness, so we need to keep track of all the types we've currently made.
To GC the type, we need some way of telling reflect
we've done so, so it can remove that type from its list of created types. Probably something akin to Java's weak references.
All the interface tables are allocated in persistent memory, not on the heap, so that would need to change also.
The compiler has a bunch of assumptions about types and interface tables never being GCd (e.g. the first word of an interface isn't a pointer that GC needs to traverse), that would need finding and fixing also.
Somewhat related to #20461
Could you split the the runtime type into two parts: a persistent-alloc single word indirection pointer to the second GC-able part with all the fields? But that's only a constant factor improvement and just delays the problem, probably.
I've just found out that the API framework I've developed leaks memory as I make heavy use of reflect.StructOf. Perhaps there should be a note on the reflect package about types not being garbage collected ?
I also believe this just needs to be documented better and needs no fix. The reflect package is an expert interface and as such the user of it needs to take pre-cautions and not the Go team.
Type identity by pointer and off-heap type information seem to be more valuable to me at least than making weird usages of an expert level API more convenient and safe.
Type identity by pointer and off-heap type information
That sounds like a cop-out to me, I'm afraid. I'm not convinced that allowing types to be GC'd necessarily implies that either of those two things cannot be done.
While this might seem like a minor issue for now, if we ever fix Go's plugin system, I think it will be more important.
Also, there's nothing in the reflect package that says "do not create unbounded numbers of new types because you'll cause a memory leak". Perhaps it should, but I'd much prefer that the issue was actually fixed, even if it takes a while.