I am writing my first webserver/webservices program in Go and I realized that the RSIZE (as shown by the command line program "top") grows after repeating the same request to my webservices. Does that means there is a memory leak?
I also noticed that both my app and the go process on "top" have a VSIZE of 139GB (both of them exactly that size). Is it normal?
I am using Go 1.1.2 on OS X 10.8
Many Thanks
Memory leaks are very common in almost any language, including garbage collected languages. Go is not an exception. A reference to an object, if not properly managed, may be left assigned even if unused.
This is detailed in this answer: How to get variable memory size of variable in golang? So the answer is on my 64-bit architecture: 48 bytes. A map of type map[string]int with an initial capacity of 100 now requires 4176 bytes (on 64-bit arch). The default initial capacity is around 7 if not specified explicitly.
Only the values stored in the memory managed by the stack are changed. This makes the process of storing and retrieving data from the stack very fast since there is no lookup required. We can just store and retrieve data from the top most block on it. Any data that is stored on the stack has to be finite and static.
pprof and flame graphs are pretty useful to analyze application memory leaks. A continuous profiler can really help you look at multiple snapshots of the profile and quickly figure out the cause of leaks. Cloud profiler is definitely a handy tool for GCP workloads.
Big VSIZE doesn't mean you're really using physical memory; wouldn't worry about that.
RSIZE growing after a single request also isn't worrying. RAM's reclaimed by garbage collection, which costs CPU cycles, so Go and other GC'd languages wait many requests until they need RAM freed up (or at least until a lot of RAM has been allocated) to run a collection. Fewer collections => less CPU time spent.
Leaks in the usual sense are rare because the GC should eventually free memory you aren't holding a reference to. If you have buffers that grow as needed but never shrink, those can have a leak-like effect, and if you accidentally hold a reference to memory that's really dead you can have problems. But unless the process keeps growing forever, I wouldn't assume you're having that problem here.
Here are some memory-management tips for Go; some indirectly apply to other languages, too:
runtime.ReadMemStats(ms)
can tell you how long your program has spent in GC, along with lots of other useful information like how much you're allocating (see runtime
module docs at http://golang.org/pkg/runtime/)Writer
instead of buffering up a big response, or reuse an object across several iterations of a loop instead of allocating each time, for instance.sync.Pool
package helps with that, and there's a nice general description of recycling (from before sync.Pool
was standard) on the CloudFlare blog.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With