【发布时间】:2016-06-01 10:52:47
【问题描述】:
来自 timer.Stop() documentation
Stop 可防止 Timer 触发。如果调用返回 true 停止计时器,如果计时器已过期或已过期,则为 false 停了下来。停止不会关闭通道,以防止从 频道成功错误。
我需要找到一种方法来销毁通过After 或NewTimer 在程序中创建的计时器对象或通道。我没有直接使用这些函数,只是另一个使用这些函数实现超时的库。我处理程序内存的请求越多,程序的内存就会不断增加,然后被杀死。
我查看了以下地方但没有太多帮助:
- https://groups.google.com/forum/#!topic/golang-nuts/A597Btr_0P8
- https://groups.google.com/forum/#!topic/golang-nuts/-xnFsH_ZRqU
- https://groups.google.com/forum/#!topic/golang-nuts/rYthykbCLHk
- https://groups.google.com/forum/#!topic/golang-nuts/hjioKxSJ3Tc
请帮忙,急需解决这个问题。
更新
可疑代码在https://github.com/gocql/gocql/blob/986e33a705412161497203d55d0669d04282f5ff/conn.go#L546
var timeoutCh <-chan time.Time
if c.timeout > 0 {
timeoutCh = time.After(c.timeout)
}
select {
case err := <-call.resp:
if err != nil {
if !c.Closed() {
// if the connection is closed then we cant release the stream,
// this is because the request is still outstanding and we have
// been handed another error from another stream which caused the
// connection to close.
c.releaseStream(stream)
}
return nil, err
}
case <-timeoutCh:
close(call.timeout)
c.handleTimeout()
return nil, ErrTimeoutNoResponse
case <-c.quit:
return nil, ErrConnectionClosed
}
我怎么知道这个?我运行 go tool pprof 来捕获 memprof,它显示的是:
【问题讨论】:
-
能否提供遇到问题的代码?
-
所以你是说对这数十万个计时器通道的引用并没有超出范围,所以它们不会被垃圾收集?
-
大家好,我已将可疑代码和 pprof memprofile 输出添加到问题中。
-
该代码没有错误,您不需要显式清理计时器(
time.After只是time.NewTimer(d).C的简写)。您的超时设置为多长时间,请求率是多少? -
@JimB 超时设置为 15 分钟,请求速率 > 3K 每秒(尽可能快)。我尝试用 time.NewTimer 替换
time.After并使用 Stop()。它更精简,但一段时间后内存仍然不足。