【问题标题】:Timer overhead causing memory overflow定时器开销导致内存溢出
【发布时间】:2016-06-01 10:52:47
【问题描述】:

来自 timer.Stop() documentation

Stop 可防止 Timer 触发。如果调用返回 true 停止计时器,如果计时器已过期或已过期,则为 false 停了下来。停止不会关闭通道,以防止从 频道成功错误。

我需要找到一种方法来销毁通过AfterNewTimer 在程序中创建的计时器对象或通道。我没有直接使用这些函数,只是另一个使用这些函数实现超时的库。我处理程序内存的请求越多,程序的内存就会不断增加,然后被杀死。

我查看了以下地方但没有太多帮助:

  1. https://groups.google.com/forum/#!topic/golang-nuts/A597Btr_0P8
  2. https://groups.google.com/forum/#!topic/golang-nuts/-xnFsH_ZRqU
  3. https://groups.google.com/forum/#!topic/golang-nuts/rYthykbCLHk
  4. 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()。它更精简,但一段时间后内存仍然不足。

标签: go channel


【解决方案1】:

我已为此合并了一个修复程序,https://github.com/gocql/gocql/pull/661 如果您遇到更多问题,请提出问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-05
    • 2015-12-21
    • 2012-07-29
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2011-04-15
    相关资源
    最近更新 更多