【问题标题】:Go's Garbage collector isn't releasing memory at the right time [duplicate]Go 的垃圾收集器没有在正确的时间释放内存 [重复]
【发布时间】:2018-04-22 07:15:21
【问题描述】:

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

根据question/answers 的说法,我发现 Golang 会自动进行垃圾收集,自己管理额外的内存并且不会立即将内存返回给操作系统。一些结果:

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

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

消耗 4GB 内存并不酷!所以我在我的代码中添加了一个 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 次以检查内存使用情况。 它工作得很好,但问题是,有没有什么标准方法可以更好地释放内存!?

我知道在某些情况下,Go 自己管理内存而不是重复从操作系统释放和取回内存是很好的,但在我的情况下,5 分钟的延迟对于释放内存来说非常重要。

【问题讨论】:

  • 在哪个操作系统上,以及 Go 的哪个实现和版本?细节很重要,所以请编辑您的问题以提供更多细节(以及动机和背景)。
  • 顺便说一句,在大多数操作系统上,Go 进程消耗 virtual memory(在其虚拟地址空间中),而不是 RAM。 RAM 本身由 OS 内核管理,而不是由 Go 程序或运行时管理。此外,过早释放内存可能会降低性能

标签: go garbage-collection


【解决方案1】:

您可能想从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

另见Linux ate my RAM

【讨论】:

    猜你喜欢
    • 2014-08-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多