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周期。
1条答案
按热度按时间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周期。