我在 stack overflow 中搜索过类似的东西,但找不到我要找的东西。如果这是一个明显的错误,我深表歉意,因为我最近才开始用 Go 编写代码,但我很感激任何提前的解释。
我目前有一个范围超过 *Ticker
值的 go 例程。
现在这个 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 can leak memory。确保在完成 go 例程后关闭创建的 *Ticker
。但是我的程序永远运行直到我杀死它。所以这个 go 例程将永远运行,直到我决定停止程序。
我知道这样想可能很愚蠢,但我认为可能是 t := range ticker.C
部分才是问题所在。因为那个循环永远不会停止,直到我杀了。所以 t
永远不会被释放。所以我认为每次循环时 :=
都会重新声明变量?然后我循环到:
for _ = range ticker.C { // completely got rid of declaration of time.Time
// do updates ...
}
到目前为止它似乎在工作......但我真的不明白为什么,或者它应该没有帮助,而且还有其他事情我做错了。
我感谢对此的任何帮助/解释。谢谢。
最佳答案
正如@Cerise Limon 所指出的,很可能是您的应用程序在其执行的逻辑中泄漏了内存。为了准确指出什么是内存泄漏,您可以使用 pprof
来显示语句使用的总内存。这是一种回答任何问题的方法,例如:
- “应用程序的哪个部分在某个时间点使用的内存最多?”
- “应用程序的哪一部分负责最多的内存分配?(字节大小)”
- “应用程序的哪一部分(如果有的话)的大小随着时间的推移而增长”
- “给定的语句/行在某个时间点使用了多少内存?”
启用 pprof 后,您可以使用以下方法获取内存配置文件:
$ curl http://localhost:8080/debug/pprof/heap > heap.0.pprof
然后您可以使用 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
这将显示您的应用程序中使用了多少内存以及哪些语句/行负责。
同样酷的是,您可以生成程序的 graphviz 图表,以便可视化和跟踪当前内存使用情况(或内存分配):
网上有很多关于 pprof 的博文(包括标准文档)。
我写了一些关于它的内容:
还有很多令人惊叹的资源,其中两个是:
关于loops - 如果永远运行,ticker.C 是否会泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55243071/