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

ax6ht2ek  于 2023-11-14  发布在  Go
关注(0)|答案(1)|浏览(134)

Go语言有一个切片垃圾收集器,只有当所有对它的引用都失效时才释放切片。它还有一个Mmap函数,返回一个[]byte,可以用Munmap()显式释放。那么这是如何与Go语言的垃圾收集器一起工作的呢?
如果我这么做会怎么样?

  1. m := syscall.Mmap(...)
  2. m2 = m[10:100]
  3. syscall.Munmap(m)
  4. a = m2[0]

字符串

qnzebej0

qnzebej01#

mmap内存就像其他来自C或Go外部的进程内存一样。Go的垃圾收集器不会扫描它。
Go语言的运行时知道自己所有的堆区域在哪里,所以它可以根据地址判断mmap内存不是Go堆的一部分。
Go结构可以指向它,但是如果你有指针从Map内存返回到Go堆,垃圾收集器将看不到它们。如果你取消Map内存,并在其中保留一个悬空指针,并试图使用它,你的程序将崩溃。
如果你使用一个在go堆中分配的大型、长期的[]byte缓冲区,并将它们替换为指向Map内存的切片,你可能会注意到,虽然你的内存占用变小了,但你的CPU使用率却上升了。这是因为,默认情况下,go的垃圾收集器是tuned to free up about half the heap on each GC cycle。因此,通过将缓冲区移出Go堆,你正在使堆的总大小变小,因此每个分配的字节的GC周期的速率上升。实际上,通过首先使用大的、长寿命的缓冲区,你已经调整了GC,使其有利于CPU吞吐量而不是内存占用。如果缓冲区被转换为mmap区域,它们对GC变得不可见,因此它看到的堆更小,并触发更多的GC周期。

相关问题