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

时间:2018-04-22 07:15:22

标签: go garbage-collection

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

根据一些question/answers,我发现Golang会自动进行垃圾收集,管理额外的内存本身并且不会立即将内存恢复到操作系统。一些结果:

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

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

消耗4GB的ram并不酷!所以我在我的代码中添加了一个Goroutine,它将额外的内存带回了操作系统。

代码:

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))
}

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

ab -c 100 -n 400000 http://127.0.0.1:8080/ping

我连续跑了10次以上的命令来检查ram的使用情况。 它的效果非常好,但问题是,是否有任何标准方式可以更好地释放内存!?

我知道在某些情况下,Go管理内存本身而不是重复释放并从操作系统中获取内存是好的,但在我的情况下,5分钟的延迟对释放内存非常重要。

1 个答案:

答案 0 :(得分:4)

您可能希望从runtime/debug

致电FreeOSMemory

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

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

不要混淆RAM使用(RAM由您的操作系统内核管理,而不是由您的Go流程管理),virtual memoryvirtual address space。阅读RSSdemand pagingthrashing

有关垃圾收集技术的概述,请阅读The GC Handbook

为了更好地了解操作系统,请阅读Operating Systems: Three Easy Pieces