Golang <-time.After() is not garbage collected before expiry

Artem OBOTUROV
Feb 7, 2019 · 1 min read

Recently I was investigating a memory leak problem in a Go application that boiled down to me not reading the documentation properly. Here’s a piece of code that caused memory consumption of multiple Gbs:

Below is the memory metrics graph from the app:

On the left side one can see the memory consumption before the fix, and on the right — after. The profiler showed that the <-time.After was the reason for the memory leak. I was really surprised until I read the doc which says:

The underlying Timer is not recovered by the garbage collector until the timer fires.

So the 9Gb of RAM that was periodically GCed suddenly made sense. We have 60K messages per second in the channel that would be about 18 million timers allocated at every given moment plus some indeterminate number waiting to be GCed.

Trivial refactoring helped to reduce memory consumption by a factor of 20.

RTFM

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store