英文:
Unable to release memory bytes buffer
问题
Go 1.18.1
pprof报告
3549.93kB 49.73% 49.73% 3549.93kB 49.73% src/lag_monitor.PublishLagMetricToDataDog
514kB 7.20% 56.93% 514kB 7.20% bufio.NewWriterSize
512.88kB 7.18% 64.11% 512.88kB 7.18% encoding/pem.Decode
512.69kB 7.18% 71.30% 1536.98kB 21.53% crypto/x509.parseCertificate
512.50kB 7.18% 78.48% 512.50kB 7.18% crypto/x509.(*CertPool).AddCert
这段代码似乎没有释放内存,根据pprof的结果,下面的函数是消耗最多内存的函数。内存图如下:
func caller() {
events := make([]string, 0)
//....
PublishLagMetricToDataDog(ctx, strings.Join(events, ","))
}
func PublishLagMetricToDataDog(ctx context.Context, events string) error {
msg := `{
"series": [%v]
}`
b := []byte(msg)
resp, err := http.Post("https://api.datadoghq.com/api/v1/series?api_key="+env.GetDataDogKey(), "application/json", bytes.NewBuffer(b))
if err != nil {
logger.Error(ctx, "Error submitting event to datadog, err =", err)
return err
}
logger.Info(ctx, resp)
return nil
}
上述函数在一个循环中被调用。由于没有全局变量,并且没有对来自PublishLagMetricToDataDog的字节切片的引用,我无法确定内存泄漏的位置。我了解了Reset()和Truncate(),但这些方法并不能释放底层内存。
英文:
Go 1.18.1
pprof report
3549.93kB 49.73% 49.73% 3549.93kB 49.73% src/lag_monitor.PublishLagMetricToDataDog
514kB 7.20% 56.93% 514kB 7.20% bufio.NewWriterSize
512.88kB 7.18% 64.11% 512.88kB 7.18% encoding/pem.Decode
512.69kB 7.18% 71.30% 1536.98kB 21.53% crypto/x509.parseCertificate
512.50kB 7.18% 78.48% 512.50kB 7.18% crypto/x509.(*CertPool).AddCert
This piece of code appears to not release memory and based on pprof, the beloew function is the one consuming most memory.Memory graph
func caller() {
events := make([]string, 0)
//....
PublishLagMetricToDataDog(ctx, strings.Join(events, ","))
}
func PublishLagMetricToDataDog(ctx context.Context, events string) error {
msg := `{
"series": [%v]
}`
b := []byte(msg)
resp, err := http.Post("https://api.datadoghq.com/api/v1/series?api_key="+env.GetDataDogKey(), "application/json", bytes.NewBuffer(b))
if err != nil {
logger.Error(ctx, "Error submitting event to datadog, err = ", err)
return err
}
logger.Info(ctx, resp)
return nil
}
Above function is called in a loop. Since there are no global variables, and no reference to the byte slice from PublishLagMetricToDataDog, I am not able to pinpoint the memory leak. I read about Reset() and Truncate(), but this does not release the underlying memory.
答案1
得分: 2
你必须关闭每个收到的 HTTP 响应的响应体。如果不这样做,可能会导致资源泄漏,就像你观察到的那样。
解决方案:
resp, err := http.Post("https://api.datadoghq.com/api/v1/series?api_key="+env.GetDataDogKey(), "application/json", bytes.NewBuffer(b))
if err != nil {
logger.Error(ctx, "Error submitting event to datadog, err =", err)
return err
}
logger.Info(ctx, resp)
_ = resp.Body.Close() // <--- 添加这行代码
return nil
}
英文:
You must close the response body for every http response you receive. Not doing so will potentially lead to resource leaks, such as the one you've observed.
Solution:
resp, err := http.Post("https://api.datadoghq.com/api/v1/series?api_key="+env.GetDataDogKey(), "application/json", bytes.NewBuffer(b))
if err != nil {
logger.Error(ctx, "Error submitting event to datadog, err = ", err)
return err
}
logger.Info(ctx, resp)
_ = resp.Body.Close() // <--- Add this
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论