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 (
"bytes"
"compress/zlib"
"fmt"
"time"
)
func main() {
timeOut := time.NewTicker(100 * time.Millisecond)
chanTest := make(chan int32)
for {
L: for { // timer part
select {
case resp := <- chanTest: // strange clause
fmt.Println("received stuff", resp)
case <-timeOut.C:
fmt.Println("break")
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(&b)
w.Write(data)
w.Close()
b.Reset()
}
}
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
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()
.