在Go中分配了很多内存。怎么修?

时间:2019-06-10 02:40:35

标签: go memory memory-leaks

数百个MB内存分配给5个MB的50个请求。内存已分配,不再释放。 如何清除记忆?为什么会发生这种情况?

我已经在家用PC和VPS上尝试过Ubuntu

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

func main() {
    fmt.Println("start")

    for i := 0; i < 50; i++ {
        go func() {
            DoRequest()
        }()
        time.Sleep(10 * time.Millisecond)
    }

    time.Sleep(10 * time.Minute)
}

func DoRequest() error {
    requestUrl := "https://blockchain.info/rawblock/0000000000000000000eebedea046425bd54626e6c56eb032e66e714d0141ea6"

    req, err := http.NewRequest("GET", requestUrl, nil)

    if err != nil {
        return err
    }

    req.Header.Set("user-agent", "free")

    httpClient := &http.Client{
        Timeout: time.Second * 10,
    }

    resp, err := httpClient.Do(req)

    if resp != nil {
        defer resp.Body.Close()
    }

    if err != nil {
        return err
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return err
    }

    fmt.Println("bodylen", len(body))

    return nil
}

分配了400MB的空间

2 个答案:

答案 0 :(得分:7)

您要为每个例程创建一个http客户端。

Http客户端被设计为一次创建并使用多次。他们是例行安全的。 它们允许连接重用和其他节省效率的工具。

在main中(而不是在您的例程中)一次创建http客户端,然后将此唯一引用传递给您的所有50个例程。


编辑:另外,虽然这可能对您没有实际的影响,但请求的顺序通常是这样的:

resp, err := httpClient.Do(req)
if err != nil {
        return err // check error first
}
defer resp.Body.Close() // no error - so resp will *NOT* be nil - so this is safe

编辑2:正如@Adrian所说:go的垃圾回收不是瞬时的-也不应该是瞬时的-因为它是一项昂贵的操作。如果您不再需要内存块,则不再引用它。让GC做好工作,让您可以专心工作!

如果您对go的GC的发展感到好奇:

答案 1 :(得分:0)

 for i := 0; i < 50; i++ {
        go func() {
            DoRequest()
        }()
        time.Sleep(10 * time.Millisecond)
    }

永远不要创建这样的go例程。始终确保以任何情况下都不能填充大(全部)内存的方式创建例程,

一种简单的解决方案是控制可以在某个时间生成(或运行)的go例程的数量。

您可以通过一次计算要运行的go例程的最大数量来预计算在最坏情况下要占用的内存,并且一个go例程可以使用max-memory。

您可以使用频道控制go-routine的实例。

请参阅此stackoverflow问题的第一个答案 Always have x number of goroutines running at any time

始终在性能和所需资源之间使用平衡的解决方案。


2019年6月11日更新

这是示例go程序 https://play.golang.org/p/HovNRgp6FxH