【发布时间】:2019-03-19 14:15:41
【问题描述】:
我已经在堆栈溢出中搜索了类似的内容,但找不到我正在寻找的确切内容。如果这是一个明显的错误,我深表歉意,因为我最近才开始用 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 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 ...
}
到目前为止,它似乎正在工作......但我真的不明白为什么,或者它应该没有帮助,而且还有其他事情我做错了。
感谢任何帮助/解释。谢谢。
【问题讨论】:
-
应用程序正在正确使用代码。如果泄漏出在这个 goroutine 中,那么问题出在
// do updates。 -
欢迎来到 StackOverflow!您在循环中返回的值只是代码关闭的时间,它可能已分配在堆栈上,并且仅在一个循环迭代的持续时间内存在。它不能泄漏。股票代码,如果它意味着你的应用程序的生命周期,那么根据定义也不能泄漏。您能否详细说明是什么让您认为您有内存泄漏以及您如何将引用的代码识别为泄漏的来源?
-
如果ticker导致内存泄漏,这意味着Go中有一个非常严重的错误,因为ticker本质上只是一个通道。
-
Go 附带了一个名为
pprof的下一级工具,它将通过显示使用的总内存和/或每个语句分配的总内存来帮助您跟踪程序中内存泄漏的确切来源。网上有大量关于如何使用它的博客文章(以及 golang.org 上的精彩文档)。我也试着解释一下medium.com/dm03514-tech-blog/… -
defer reader.Close()是直接从checkForUpdates中的循环调用的吗?如果是这样,那就是问题所在。延迟调用在函数返回时执行。
标签: loops go memory-leaks