Is time.After safe to use? or will it leak?

3,958 views
Skip to first unread message

josvazg

unread,
Nov 10, 2015, 5:43:19 PM11/10/15
to golang-nuts
I mean, the most common use of it AFAIK is to have it on a select clause to timeout some other result coming on a different channel:
http://blog.golang.org/go-concurrency-patterns-timing-out-and

So when I say "safe to use" I mean, when the timeout is not selected and the receiver goes away, will it leak or free resources?

I guess that if the function that called "case <-time.After(...):" returns and the goroutine started by After() ends, the channel reference should be eventually freed? Right?
Or will it leak somehow?

Thanks,

Jose

Ian Lance Taylor

unread,
Nov 10, 2015, 5:47:46 PM11/10/15
to josvazg, golang-nuts
Yes, you can use time.After without worrying about leaking memory.
Once the timeout expires, all resources will be released.

This is not true of time.Ticker. A time.Ticker will use up memory
until you call the Stop method. If you lose track of it entirely, the
memory will be lost until the program exits.

Ian

Jose Luis Vazquez

unread,
Nov 10, 2015, 5:52:02 PM11/10/15
to Ian Lance Taylor, golang-nuts
Thanks a lot Ian for such a quick reply!

(This list latency SLA is tight!)

Jose 

Chris Kastorff

unread,
Nov 12, 2015, 8:52:31 PM11/12/15
to Jose Luis Vazquez, Ian Lance Taylor, golang-nuts
Ian's answer, while technically correct, is misleading if I understand your question correctly. The resources for the Timer (created internally by time.After) will be released when the timeout expires, but the Timer still uses memory until that happens.

For example, if you use time.After in a tight loop which does NOT hit the timeout most of the time, you'll use far more memory than you expect; about 201 bytes per timer, in my configuration.

Test for yourself: http://play.golang.org/p/Yjs7ACcydg (you'll need to reduce the number of timers for the playground to not time out on you, but it still shows the issue.)

For me, this outputs:
    before, have 4 goroutines, 40672 bytes allocated
    after, have 9 goroutines, 201139736 bytes allocated

And top confirms the memory usage is real (physically allocated anonymous pages, in RSS).

I use time.After for timeouts I expect to be hit in the common case (e.g. a cancelable sleep, like for { doWork(); select { case <-cancel: return; case <-time.After(loopInterval): } }) but not for timeouts I expect to be missed in the common case (e.g. showing a warning if a channel blocks for a while). For those timeouts I expect to be missed in the common case, I use Timer directly, Stop()ing it when I'm done with it.

--
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 golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jose Luis Vazquez

unread,
Nov 14, 2015, 6:37:32 AM11/14/15
to Chris Kastorff, Ian Lance Taylor, golang-nuts
Thanks Chris 

That makes sense. Resources are eventually freed but that might not be good enough if you spawned many of these. 

Will be using timer in my case and I am building bursts of goroutines querying a fleet of nodes.

Jose
Reply all
Reply to author
Forward
0 new messages