【发布时间】:2021-08-22 10:18:51
【问题描述】:
getAPIData 函数用于获取 HTML 字符串,需要每 5 秒调用一次。我使用runtime.ReadMemStats 函数检查了内存使用情况。
如下面的输出所示,内存缓慢上升,但从未下降。
Alloc = 1 MiB TotalAlloc = 2 MiB Sys = 71 MiB NumGC = 1
...
Alloc = 3 MiB TotalAlloc = 4 MiB Sys = 71 MiB NumGC = 1
...
Alloc = 3 MiB TotalAlloc = 6 MiB Sys = 71 MiB NumGC = 2
Alloc = 2 MiB TotalAlloc = 7 MiB Sys = 71 MiB NumGC = 3
...
Alloc = 3 MiB TotalAlloc = 9 MiB Sys = 71 MiB NumGC = 3
...
Alloc = 3 MiB TotalAlloc = 10 MiB Sys = 71 MiB NumGC = 4
我为我的问题制作了示例代码。我应该怎么做才能修复那个内存泄漏?
package main
import (
"fmt"
"io/ioutil"
"net/http"
"runtime"
"time"
)
func getAPIData() (string, error) {
req, err := http.NewRequest("GET", "https://google.com/", nil)
if err != nil {
//fmt.Println(err.Error())
return "", err
//panic(err)
}
req.Header.Add("User-Agent", "Mozilla/5.0")
client := &http.Client{Timeout: 3 * time.Second}
resp, err := client.Do(req) // cuase of memory leak
if err != nil {
fmt.Println(err.Error())
return "", err
//panic(err)
}
defer resp.Body.Close()
bytes, err2 := ioutil.ReadAll(resp.Body)
if err2 != nil {
fmt.Println(err2.Error())
return "", err2
//panic(err)
}
return string(bytes), nil
}
func PrintMemUsage() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
fmt.Printf("\tNumGC = %v\n", m.NumGC)
}
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}
func main() {
for range time.Tick(5 * time.Second) {
_, _ = getAPIData()
PrintMemUsage()
}
}
【问题讨论】:
-
这没有显示任何泄漏。
TotalAlloc是已分配的金额;如果释放一些内存,然后再次分配,则“分配的总量”会增加。随着每个分配的对象被释放,释放的计数也随之增加;Alloc值减小,但TotalAlloc值不减小。 -
由于您的
Alloc值稳定在 3 MiB 左右,因此很明显没有实际泄漏。如果 TotalAlloc 为 10 且 Alloc 为 3,则必须沿途释放 7。 -
了解 totalalloc 值。谢谢..
标签: go memory-leaks