Go的垃圾收集器未在正确的时间释放内存

had*_*244 0 garbage-collection go

我编写了一个简单的http golang网络服务器来测试Go垃圾回收(释放无法访问的指针的内存),但是在strees测试中,我知道它消耗了过多的内存。

根据一些问题/答案,我发现Golang会自动进行垃圾回收,管理额外的内存本身,并且不会立即将内存退回给OS。一些结果:

  • 网络服务器在大约5分钟后释放ram。

  • 网络服务器会消耗ram直到达到特定级别并且请求更多连接不会获得更多内存(在我的情况下约为4GB)

消耗4GB的内存并不酷!因此,我在代码中添加了Goroutine,以将额外的内存返回给OS。

代码:

type t struct{
    a       []string
    b       map[string]string
}
var x t = t{
    a:  []string{"1","2"},
    b:  make(map[string]string),
}

func handler(w http.ResponseWriter, r *http.Request) {
    x := &t{}
    fmt.Fprintf(w, "pong", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/ping", handler)
    go func(){
        for {
            time.Sleep(10 * time.Second)
            fmt.Println("Free up memory...")
            debug.FreeOSMemory() 
        }

    }()
    log.Fatal(http.ListenAndServe(":8080", nil))
}
Run Code Online (Sandbox Code Playgroud)

对于压力测试,我使用Apache Bench

ab -c 100 -n 400000 http://127.0.0.1:8080/ping
Run Code Online (Sandbox Code Playgroud)

我连续10次以上运行命令以检查ram的使用情况。它工作得很好,但是问题是,是否有任何标准方法可以更好地释放内存!

我知道在某些情况下,Go可以自行管理内存,而不是从操作系统中重复释放和获取内存,这是一件好事。但是在我的情况下,延迟5分钟对于释放内存非常重要。

Bas*_*tch 6

您可能要从以下位置调用FreeOSMemory:runtime/debug

但是您可能不应该。尝试针对您的特定应用程序和用法(可能使用SetGCPercent)调整GC 。FreeOSMemory经常使用可能会降低性能,因此请务必进行基准测试。

注意,垃圾收集实现在Go的最新版本中有所改进,并且在各种Go实现中(例如,在GCC Go中)有所不同。

不要混淆RAM的使用(RAM由您的OS内核管理,而不是由Go进程管理),虚拟内存虚拟地址空间。了解有关RSS需求分页颠簸的信息

有关垃圾回收技术的概述,请阅读《 GC手册》

为了更好地理解操作系统,请阅读《操作系统:三篇简单的文章》。

另请参见Linux吃了我的RAM