ticker.C是否会永久运行而泄漏内存?

时间:2019-03-19 14:15:42

标签: loops go memory-leaks

我已经在堆栈溢出中搜索了类似的内容,但是找不到我想要的东西。如果这是我最近刚开始使用Go编写时的明显错误,我深表歉意,但是我很感谢提前做出的任何解释。 我目前有一个go例程,其范围超过*Ticker的值。 现在,此go例程在我的程序运行期间一直运行,因为它检查必要的更新。我开始认识到我的程序会随着时间的推移慢慢泄漏内存。运行20到30小时后,它开始变得非常引人注目。

func (s *Server) checkForUpdates() { // go routine
    ticker := time.NewTicker(time.Minute * time.Duration(s.checkTime)) //x.checkTime = 2 minutes
    defer ticker.Stop()
    for t := range ticker.C { // will loop every 2 minutes
         fmt.Println("the update check happened at %d\n", t)
         // do the updates
    }
}

我将泄漏范围缩小到了go例程,并一路读取Time会泄漏内存。完成go例程后,请确保关闭创建的*Ticker。但是,我的程序将永远运行直到我将其杀死。因此,该go例程将永远运行,直到我决定停止程序为止。 我知道这可能很愚蠢,但我认为可能是问题所在的t := range ticker.C部分。因为直到我杀了那个循环永远都不会停止。因此t永远不会被释放。因此,我认为:=每次循环时都会重新声明变量吗?然后,我循环到:

for _ = range ticker.C { // completely got rid of declaration of time.Time
   // do updates ...
}

到目前为止,它似乎一直在起作用……但是我真的不明白为什么,或者它应该没有帮助,还有我做错了其他事情。

我对此表示感谢。谢谢。

1 个答案:

答案 0 :(得分:3)

As @Cerise Limon pointed out it is most likely your application leaking memory in the logic its doing. In order to pinpoint exactly what is leaking memory you can use pprof to show the total memory in use by statement. This is a method for answering any question like:

  • "Which part of the application is using the most memory at a point in time?"
  • "Which part of the application is responsible for the most memory allocations? (in byte size)"
  • "which part of the application (if any) is growing in size over time"
  • "how much memory is a given statement/line using at a point in time?"

Once pprof is enabled you can take memory profiles by using:

$ curl http://localhost:8080/debug/pprof/heap > heap.0.pprof

You can then interact with the profile using the cli:

$ go tool pprof pprof/heap.3.pprof
Local symbolization failed for main: open /tmp/go-build598947513/b001/exe/main: no such file or directory
Some binary filenames not available. Symbolization may be incomplete.
Try setting PPROF_BINARY_PATH to the search path for local binaries.
File: main
Type: inuse_space
Time: Jul 30, 2018 at 6:11pm (UTC)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) svg
Generating report in profile002.svg
(pprof) top20
Showing nodes accounting for 410.75MB, 99.03% of 414.77MB total
Dropped 10 nodes (cum <= 2.07MB)
      flat  flat%   sum%        cum   cum%
  408.97MB 98.60% 98.60%   408.97MB 98.60%  bytes.Repeat
    1.28MB  0.31% 98.91%   410.25MB 98.91%  main.(*RequestTracker).Track
    0.50MB  0.12% 99.03%   414.26MB 99.88%  net/http.(*conn).serve
         0     0% 99.03%   410.25MB 98.91%  main.main.func1
         0     0% 99.03%   410.25MB 98.91%  net/http.(*ServeMux).ServeHTTP
         0     0% 99.03%   410.25MB 98.91%  net/http.HandlerFunc.ServeHTTP

Which will show you how much memory is inuse in your application and which statements/lines are responsible.

What's also cool is that you can generate graphviz charts of your program in order to visualize and trace current memory usage (or memory allocations):

enter image description here


There are quite a few blog posts about pprof online (including standard documentation).

I wrote a bit about it:

And then there are many amazing resources, two of which are: