Mysterious RSS memory spike

Skip to first unread message

Manish R Jain

Aug 23, 2020, 11:05:22 AM8/23/20
to golang-nuts
Hey Gophers,

I'm puzzled by a mysterious RSS memory spike in my Go program, when all memory allocations are happening via Cgo. I assert that there are no memory leaks in the program. And have written another C program with similar logic which does NOT show RSS memory spiking. So, I suspect this is something to do with Go memory.


This PR creates a Go memtest program, which does this:
- Uses z.Calloc and z.Free to allocate Go struct (S) and a byte slice inside it. All allocations are happening in Cgo, and being type casted into Go. No allocations are happening in Go (except a 32 MB fill slice).
- z.NumAllocBytes is tracking memory allocated and freed by these calls.
- Increases memory usage to 16 GB (as reported by z.NumAllocBytes).
- Decreases it back to 1 GB.
- Repeats this cycle.
- On Ctrl+C, it deallocates everything and asserts that Cgo memory allocated is zero.

I was concerned about memory fragmentation, so created a very similar C program which does the same thing (memtestc).

Please feel free to run either of the Go or C programs. They should compile and run easily.


Run the program with: `go build . && ./memtest` . Go pprof heap shows 32 MB used, to account for the fill slice. However, RSS reported keeps roughly increasing every cycle.

I'm using Go 1.14.4 and on it, RSS jumps to 22GB after a few cycles. memtestc (C equivalent, compiled with gcc) does not show this behavior. The RSS goes down to 1GB-ish every cycle.

Any clues why the RSS is much higher than expected in Go and keeps climbing in Go?


Mike Spreitzer

Aug 23, 2020, 2:25:37 PM8/23/20
to, golang-nuts
BTW, how are you measuring RSS? That is a trick all by itself! See

Mike wrote on 08/23/2020 11:04:47 AM:
> ?
> Manish
> Founder,
> [image removed]
> --
> You received this message because you are subscribed to the Google
> Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to
> To view this discussion on the web visit
> d/msgid/golang-nuts/

Vladimir Varankin

Aug 24, 2020, 5:05:00 AM8/24/20
to golang-nuts

I haven't looked deep but I recall there had been a note about runtime change in Go 1.13's That is

> The runtime is now more aggressive at returning memory to the operating system to make it available to co-tenant applications [..] However, on many OSes, including Linux, the OS itself reclaims memory lazily, so process RSS will not decrease until the system is under memory pressure. 

Could that be the behaviour you observe (although, since you don't see the same in C implementation, I might be confused, sorry in advance).

Aug 24, 2020, 8:03:32 AM8/24/20
to golang-nuts
If it helps any, I do not see this in Windows 10. After 5,000 iterations the "low memory" mark, as reported by windows, is still just 1,101MB.

Miha Vrhovnik

Aug 24, 2020, 1:42:21 PM8/24/20
to golang-nuts
Hey, Vlad,
it's not that. we have a similar or rather the exactly the same problem... where the OS doesn't claim the memory back.. this is also annoying to the point we had to disable memory under pressure notifications for that specific host.
Also valgrind doesn't report any leaks... simulating the same with C app the memory is returned to the OS almost immediately.

Fortunately for us this is in the worker processes where we can restart them after about 1000 iterations.


Manish R Jain

Aug 24, 2020, 6:01:15 PM8/24/20
to golang-nuts
Thanks to Kale in darkarts Slack channel, we were able to identify the issue. The default C Calloc has major memory fragmentation issues due to Go's multi-threaded execution (or so is our theory). Switching Cgo to use jemalloc instead fixed the issue. The RSS now goes down to (close to) 1GB on every cycle. Anyone interested can see the linked PR for code updates.

I'll write a blog post about this soon-ish.

Reply all
Reply to author
0 new messages