为了账号安全,请及时绑定邮箱和手机立即绑定

一旦被 bytes.Buffer 占用,就无法释放内存

一旦被 bytes.Buffer 占用,就无法释放内存

Go
qq_花开花谢_0 2022-01-10 18:52:00
我收到compressedbytes[]byte 类型的压缩 ASCII 文本字节。我面临的问题是,以下过程占用了大量内存,在函数结束后没有被释放,并且在程序的整个运行时仍然被占用。    b := bytes.NewReader(compressedbytes)    r, err := zlib.NewReader(b)    if err != nil {        panic(err)    }    cleartext, err = ioutil.ReadAll(r)    if err != nil {        panic(err)    }我注意到正在使用的类型是bytes.Buffer并且这种类型具有Reset()和Truncate()功能,但它们都不允许释放曾经被占用的内存。该文档的Reset()状态如下:重置将缓冲区重置为空,但它保留底层存储以供将来写入使用。重置与截断(0)相同。如何取消设置缓冲区并再次释放内存?我的程序在需要 2 小时的运行期间需要大约 50MB 的内存。当我导入 zlib 压缩的字符串时,程序需要 200 MB 内存。谢谢你的帮助。=== 更新我什至为解压创建了一个单独的函数,并runtime.GC()在程序从该函数返回但没有成功后手动调用垃圾收集器。// unpack decompresses zlib compressed bytesfunc unpack(packedData []byte) []byte {    b := bytes.NewReader(packedData)    r, err := zlib.NewReader(b)    if err != nil {        panic(err)    }    cleartext, err := ioutil.ReadAll(r)    if err != nil {        panic(err)    }    r.Close()    return cleartext}
查看完整描述

2 回答

?
ibeautiful

TA贡献1993条经验 获得超5个赞

有些事情要清楚。Go 是一种垃圾收集语言,这意味着当这些变量变得无法访问时,垃圾收集器会自动释放变量分配和使用的内存(如果您有另一个指向该变量的指针,它仍然算作“可访问”)。

释放的内存并不意味着它会返回给操作系统。释放内存意味着可以回收内存,如果需要,可以将其重用于另一个变量。因此,从操作系统来看,您不会仅仅因为某些变量变得无法访问而立即看到内存减少,并且垃圾收集器检测到这一点并释放了它使用的内存。

但是,如果一段时间(通常是 5 分钟左右)不使用,Go 运行时会将内存返回给操作系统。如果在此期间内存使用量增加(并且可选地再次缩小),则内存很可能不会返回给操作系统。

如果您等待一段时间并且不再分配内存,则释放的内存最终将返回给操作系统(显然不是全部,但未使用的“大块”将是)。如果您不能等待这种情况发生,您可以调用debug.FreeOSMemory()强制执行此行为:

FreeOSMemory 强制进行垃圾收集,然后尝试将尽可能多的内存返回给操作系统。(即使不调用它,运行时也会在后台任务中逐渐将内存返回给操作系统。)


查看完整回答
反对 回复 2022-01-10
?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

当没有人再引用它时,它最终会被释放,Go 有一个相当不错的 GC。


查看完整回答
反对 回复 2022-01-10
  • 2 回答
  • 0 关注
  • 341 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信