I am very new to Golang, but have lots of Java and C experience.
My application has a fairly complex,hierarchical object model built from a database, ORM-style, which is intended to be long-lived. The structures are built up using pointers created with new and/or make.
There are situations when I need to flush the current objects from memory and rebuild them from the DB. Is it possible to encourage Golang to reclaim the memory by traversing the structures from the lower levels, setting references to nil?
Is there a better way to do this?
(I am starting to realize that this architecture is not really typical for Go, which prefers to keep things on the stack. However, I am not free to discard it and start over, or to change to a different programming language.)
Thanks in advance for any guidance.
CodePudding user response:
The point of garbage collected languages is that you don't have to worry about memory management, you don't have to worry about memory allocations and deallocations.
The general principle is: as long as you have a "reference" to some object, it will not be garbage collected; and objects that no one has a reference of, will be garbage collected.
This principle is of course "recursive". If you have an A
object holding a pointer to a B
object, and there's only a single reference to A
(and no one else has a reference to B
), once that reference "goes away", both A
and B
will be garbage collected.
So if you want some complex object hierarchy to be freed, just make sure you don't keep pointers to it, and it will be freed automatically. You do not have to traverse it recursively to zero pointers.
There is one important thing to keep in mind though: If you have a pointer to some "part" of an object, that will keep the whole object in memory. For example if you create a struct, and take the address of one of its fields and store it somewhere, that pointer will keep the whole struct in memory. Similarly, if you create a slice and you take the address of one of its elements (and store it), that will keep the whole slice (or more precisely its backing array) in memory. This also applies if you reslice the slice to "hide" elements, e.g.:
s := make([]*int, 10)
s[8] = new(int)
s = s[:2]
Here we created a slice of 10 int
pointers, we assigned a pointer to the index 8
, then resliced the slice to only hold the first 2 elements. There is a backing array in the background with storage for 10 pointers, which is not cleared by the above slicing operation, so the pointed int
(at index 8
in the original slice) will remain in memory (as long as you have a reference to the slice or its backing array). For details, see Does go garbage collect parts of slices?
See related questions:
Cannot free memory once occupied by bytes.Buffer
CodePudding user response:
Thank you. I understand this principle already. The issue is being sure that I don't have any references to any part of the these structures. That's tricky given that these structure instances reference each other in complicated ways.