Unfortunately, I can't post the full program, but it is a long-running process that makes many HTTP calls (a few hundred a minute), and the process size grows around 100MB/hour. I can upload a full test program if you want, but the HTTP request part looks like the code below. When I use the profiler after a few hours, it looks like this:
Adjusting heap profiles for 1-in-524288 sampling rate
Welcome to pprof! For help, type 'help'.
(pprof) top10
Total: 767.5 MB
484.0 63.1% 63.1% 484.0 63.1% cnew
66.0 8.6% 71.7% 66.0 8.6% newdefer
42.0 5.5% 77.1% 110.5 14.4% crypto/x509.parseCertificate
37.5 4.9% 82.0% 37.5 4.9% crypto/rc4.NewCipher
20.0 2.6% 84.6% 283.0 36.9% net/http.(*Transport).dialConn
12.5 1.6% 86.3% 346.0 45.1%
code.google.com/p/go-imap/go1/imap.DialTLS
9.5 1.2% 87.5% 416.0 54.2% main.watchAccount
9.0 1.2% 88.7% 9.0 1.2% encoding/asn1.parsePrintableString
8.0 1.0% 89.7% 8.0 1.0%
code.google.com/p/go-imap/go1/imap.(*Client).setCaps
7.0 0.9% 90.6% 7.0 0.9% crypto/sha1.New
In addition, when I pass in the --heapcheck option to pprof and spit out a PDF, it also shows crypto/x509.parseCertificate, crypto/rc4.NewCipher, and net/http.(*Transport).dialConn as potential leaks.
I've tried pretty hard to locate anything inside my code that could be causing this, and it sure seems like it's coming from the HTTP library.
- Ian
========
var token_channel chan bool = make(chan bool, 25)
func makeRequest() {
token_channel <- true
req, err := http.NewRequest("GET", url, nil)
req.SetBasicAuth("username", os.Getenv("PASS"))
http_rsp, err := http_client.Do(req)
<-token_channel
if err != nil {
log.Printf("Error refreshing access token: %s", err)
return
}
buf := make([]byte, 1024)
io.ReadFull(http_rsp.Body, buf)
// make sure we close the message body
defer http_rsp.Body.Close()