Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use "time.After" may cause a memory leak #518

Open
levin-go opened this issue Jul 10, 2021 · 7 comments
Open

Use "time.After" may cause a memory leak #518

levin-go opened this issue Jul 10, 2021 · 7 comments

Comments

@levin-go
Copy link

image

@MattBrittan
Copy link
Contributor

Please point out where in this library the memory leak is?

The comment you pasted does not say that time.After causes a memory leak; just that resources are not freed until "the timer fires". This means that a small amount of memory may not be released as rapidly as possible but I think referring to this as a "memory leak" is an exaggeration. Using time.After in a tight loop could definitely cause issues but we don't do that (from a quick scan of the code),

There is a potential in that a very high volume publisher may see extra memory usage (due to the call to time.After(time.Second * 30) (by default) in Publish) which may cause an issue if you have very low resources. You are welcome to submit a PR for this if its impacting you.

@levin-go
Copy link
Author

Yes, we now use mqtt to communicate in the intranet. The speed of sending and receiving is very fast, about 10-20ms to send data. In the Publish function, time. After will be called frequently, so the memory will continue to grow for a long time to stabilize.I think it's more reasonable to use time.NewTicker here.This can solve unnecessary memory occupation.

@MattBrittan
Copy link
Contributor

MattBrittan commented Jul 10, 2021

Why are you preferring time.NewTicker over time.NewTimer? (a ticker will fire periodically, a timer will fire once).

The change should be fairly simple:

t := time.NewTimer(time.Second * 2)
defer t.Stop() // As long as we are not in a loop!

select {
   case <-x: // Whatever other actions are needed 
...	
   case <-t.C:
      // Do whatever
}

@levin-go
Copy link
Author

Yes, just like you said. For devices with very small memory (for example, my embedded device has only 128M memory), I think this is more reasonable.

@levin-go
Copy link
Author

Whether time. Newticker or time. Newtimer, resources will be released after calling Stop. It's more reasonable to use time. Newtimer here. Thank you for your correction.

@jonaz
Copy link

jonaz commented Mar 10, 2022

FYI this is the only way to avoid memory leak:

  delay := time.NewTimer(time.Second)
 
  select {
  case <-delay.C:
     // do something after one second.
  case <-ctx.Done():
     // do something when context is finished and stop the timer.
     if !delay.Stop() {
        // if the timer has been stopped then read from the channel.
        <-delay.C
     }    
  }

@jyc6
Copy link

jyc6 commented Oct 18, 2022

我的也是这个,这个问题造成了内存泄漏,这个文件在哪,怎么修改

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants