内存消耗激增

huangapple go评论81阅读模式
英文:

Memory consumption skyrocket

问题

我有一个程序,内存不断增长。我不确定是内存泄漏还是缓冲区不断增长。

我成功地隔离了问题,但我仍然找不到问题所在。

有一些奇怪的行为:如果我删除压缩部分,泄漏就消失了。
所以我认为问题就在那里。但是,如果我(仅)删除了switch语句中的chanTest子句,泄漏也会消失。
有人可以确认问题,并解释为什么会出现这样的行为吗?
我正在使用go1.0.3版本。

谢谢!

以下是程序代码(每100毫秒压缩一些虚拟数据):

package main

import (
    "bytes"
    "compress/zlib"
    "fmt"
    "time"
)

func main() {
    timeOut := time.NewTicker(100 * time.Millisecond)
    chanTest := make(chan int32)

    for {
        L: for {  // 定时器部分
            select {
                case resp := <- chanTest: // 奇怪的子句
                    fmt.Println("received stuff", resp)
                case <-timeOut.C:
                    fmt.Println("break")
                    break L
            }
        }
        timeOut = time.NewTicker(100 * time.Millisecond)

        // 压缩部分
        data := []byte{1, 2, 3, 4, 5, 6, 7}
        var b bytes.Buffer
        w := zlib.NewWriter(&b)
        w.Write(data)
        w.Close()

        b.Reset()
    }
}
英文:

I have a program where memory keep growing. I'm not sure if it's a memory leak or just a buffer that keep growing.

I successfully isolated the problem, but I still can't find the problem.

There is some strange behavoir: if I remove the compression part, the leak disappear.
So I assume it's there. BUT if I (only) remove the clause with chanTest in the switch, the leak disappear too.
Could someone confirm the problem and explain me why it has such behavoir?
I'm using go1.0.3

Thanks!

Here is the program: ( it compress some dummy data every 100ms )

package main

import (
    &quot;bytes&quot;
    &quot;compress/zlib&quot;
    &quot;fmt&quot;
    &quot;time&quot;
)

func main() {
    timeOut := time.NewTicker(100 * time.Millisecond)
    chanTest := make(chan int32)
 
    for {	    
	    L: for {  // timer part
		    select {
		        case resp := &lt;- chanTest: // strange clause
			        fmt.Println(&quot;received stuff&quot;, resp)
		        case &lt;-timeOut.C:
			        fmt.Println(&quot;break&quot;)
			        break L
		        }
	       }
	    timeOut = time.NewTicker(100 * time.Millisecond)

	    // compression part
	    data := []byte{1, 2, 3, 4, 5, 6, 7}
	    var b bytes.Buffer
	    w := zlib.NewWriter(&amp;b)
	    w.Write(data)
	    w.Close()

	    b.Reset()
    }
}

答案1

得分: 3

你在循环内部启动了一个新的 Ticker,但没有在原始的 Ticker 上调用 .Stop()。由于 Ticker 在间隔时间内运行,你最终会得到多个 Ticker 同时运行的情况。

调用 .Stop() 来停止之前的 Ticker 从技术上 是可行的:

timeOut.Stop()
timeOut = time.NewTicker(100 * time.Millisecond)

...但似乎违背了它的目的。相反,只需不在循环中创建新的 Ticker,原始的 Ticker 将继续运行:

// timeOut = time.NewTicker(100 * time.Millisecond) // 不需要
英文:

You're starting a new Ticker inside the loop without calling .Stop() on the original. Since the Ticker runs at an interval, you end up with multiple Tickers continuing to run at the same time.

Calling .Stop() to halt the previous one would technically work:

timeOut.Stop()
timeOut = time.NewTicker(100 * time.Millisecond)

...but seems to defeat the purpose of it. Instead, just don't make new Tickers in the loop, and the original will continue to run:

// timeOut = time.NewTicker(100 * time.Millisecond) // not needed

答案2

得分: 2

在2013年2月25日之后的golang tip中有一个修复此问题的方法(修订版本1c50db40d078)。如果您运行hg pull; hg update来更新Go的源代码并重新编译Go发行版,那么内存消耗问题应该会消失。

然而,仅仅这样还不能使程序正确 - 它只是修复了异常高的内存消耗。正确的实现需要调用timeout.Stop()

英文:

There is a fix for this issue in golang tip newer than 25-Feb-2013 (revision 1c50db40d078). If you run hg pull; hg update to update Go's source code and recompile your Go distribution then the memory consumption issue should disappear.

However, this alone does not make the program correct - it only fixes the unusually high memory consumption. A correct implementation needs to be calling timeout.Stop().

huangapple
  • 本文由 发表于 2013年2月6日 00:48:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/14712586.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定