通道和内存泄漏

时间:2014-08-29 00:58:35

标签: memory-leaks go channel

我正在尝试开发一个持续运行的程序。

它应该每隔sleepPool秒从数据库中提取一些数据,并以非阻塞的方式“处理”信息(至少这是我正在尝试做的事情)。

问题是内存不断增长,所以我想知道我是否做错了。

以下是我程序的摘录。

var uCh = make(chan *user, buffLimit)     //emits new users to process
var statsCh = make(chan *user, buffLimit) //emits new users to store

func main() {

    go emitUser(db)
    go consumeUser(db)

    for ur := range statsCh {
      log.Infoln(ur)
    }
}

func emitUser(db *sql.DB) {
    for {
        time.Sleep(sleepPool * time.Second)
        log.Infoln("looking for new users")
        rows, err := rowsD.Query()
        for rows.Next() {
            uCh <- usr
        }
    }
}

func consumeUser(db *sql.DB) {
    for usr := range uCh {
        go func(usr *user) {
            //do something with the user
            statsCh <- usr
        }(usr)
    }
}

我读过我可能需要关闭通道,以便gc可以回收内存,但我不知道该怎么做(因为程序应该连续运行),如果我真的需要这样做,因为始终读取数据(由main范围保证),因此我假设内存已被回收。

2 个答案:

答案 0 :(得分:3)

你没有足够的时间让GC开始,等待一个小时然后检查内存。

如果你真的想要(糟糕的想法并且会减慢你的程序)强制它释放内存你可以使用类似的东西:

import "runtime/debug"
//........
func forceFree() {
    for _ = range time.Tick(30 * time.Second) {
        debug.FreeOSMemory()
    }
}

func init() {
    go forceFree()
}

答案 1 :(得分:0)

这段代码可以做很多无害的传递,但不应泄漏任何东西。

我的猜测是rowsD.Query方法有某种缓存或其他泄漏。

当然,它可能只是碎片,或垃圾收集器的人工制品(在这种情况下,你应该看到内存使用水平关闭,甚至下降,随着时间的推移)。