mmap 如何与 Go 的垃圾收集器交互?

问题描述 投票:0回答:1

Go 有一个切片垃圾收集器,仅当对切片的所有引用都已失效时才释放该切片。它还具有一个 Mmap 函数,它返回一个

[]byte
,可以使用
Munmap()
显式释放它。那么这如何与 Go 的垃圾收集器一起工作呢?

如果我这样做会发生什么?

m := syscall.Mmap(...)
m2 = m[10:100]
syscall.Munmap(m)
a = m2[0]
go garbage-collection mmap
1个回答
0
投票

mmap
内存的作用与来自 C 或 Go 外部的任何其他进程内存类似。 Go 的垃圾收集器不会扫描它。

Go 的运行时知道它自己的所有堆区域在哪里,因此它可以仅根据地址判断

mmap
内存不是 Go 堆的一部分。

Go 结构可以指向它,但是如果您有从映射内存返回 Go 堆的指针,垃圾收集器将看不到它们。如果您取消映射内存并在其中保留一个悬空指针并尝试使用它,您的程序将会崩溃。

如果你的程序使用了在 go 堆中分配的大的、寿命长的

[]byte
缓冲区,并将它们替换为指向映射内存的切片,你实际上可能会注意到,虽然你的内存占用量变小了,但你的 CPU 使用率却上升了。这是因为,默认情况下,Go 的垃圾收集器调整为在每个 GC 周期释放大约一半的堆。因此,通过将缓冲区移出 Go 堆,可以使堆的总大小变小,因此分配的每个字节的 GC 周期率会上升。实际上,通过首先使用大的、寿命长的缓冲区,您已经调整了 GC,以支持 CPU 吞吐量而不是内存占用。如果缓冲区被转换为
mmap
区域,它们对 GC 来说将变得不可见,因此它会看到更小的堆,并触发更多 GC 周期。

© www.soinside.com 2019 - 2024. All rights reserved.