golang 内存疑问

问题描述

初学 golang ,没太多接触编译型语言,不太了解其内存的回收机制,在并发测试 http server 时发现内存会随着测试的进行持续走高,待测试结束后该内存会一直占用不会减少。一个请求响应的周期结束后占用的内存不应被释放掉吗,还是说这里需要手动回收呢?我应该怎样去理解和解决呢?谢谢

深度截图_选择区域_20200114132215.png

环境

kubuntu 19.10
go 1.13.4

相关代码

package main

import (
    "net/http"
)

func main() {
    http.ListenAndServe(":8080", nil)
}
ulimit -n 65535
ab -n 100000 -c 10000 http://127.0.0.1:8080/

类似问题:https://stackoverflow.com/que...

阅读 231
评论 1月14日提问
    1 个回答
    zuch
    • 4.3k

    首先,这个编译型语言关系不大,很多具有垃圾回收的语言都会遇到这个问题

    其次,既然 Golang 有垃圾回收,当然就不需要你手动回收了

    最后,那为什么程序的内存不会降低呢?有几种可能:

    1. Golang 的 http 库有 bug,会导致内存泄漏
    2. 内存已经被 runtime 回收,但并没有归还给操作系统
    3. 内存还没有被 runtime 回收

    解决方案:

    1. 如果 http 有 bug (当然,出现的可能比较小,需要分析 http 源码),可以去给官方提 issue,等官方修复
    2. 你只看了操作系统的内存分析,并不代表程序没有进行垃圾回收,因为对于回收的内存,runtime 并不会立即归还操作系统,而是对其重用,这就避免了一些 alloc 系统调用的开销,对此你可以使用 pprof 库查看 golang 自己的 profile
    3. 垃圾回收是有代价的,所以 runtime 不会一直监视所有分配的内存,一旦不被引用就立马回收;而是周期性地进行垃圾回收。对此,你可以手动调用 runtime 库的 GC 函数来强制垃圾回收(当然这并不是什么好主意)

    所以结论是,你并不需要做什么,因为你并没有做错什么

    评论 赞赏
      撰写回答

      登录后参与交流、获取后续更新提醒