在 Go 的 GMP(goroutine, system thread, context)模型中,一个 goroutine 可能会产生许多对象并将它们放在 P(堆内存?)中,P 上的所有数据在停放时是否会复制到 G 的堆栈中?如果是这样,G 的栈可能会变得非常大,这使得 P 的设计显得毫无意义,但如果不是,调度器如何解决多个 G 的数据同时存储在 P 中的问题呢?如果 G 想在另一个 P 上执行,那是不可能的。我的问题是当g停放时,所有数据都会复制到G'堆栈吗?为什么在执行 G 时不把所有数据都放在 G 上?
1 回答
翻翻过去那场雪
TA贡献2065条经验 获得超14个赞
您的问题存在一个基本的误解:mcache
不是堆栈的占位符,而是堆上小分配的捷径。它拥有预先分配的内存块,可以分配给特定的 goroutine,避免锁定。
编译器决定是否必须在堆上分配特定变量。一旦这样做,这将永远不会被复制回 stack。
现在的问题是如何尽可能有效地从堆中分配内存。这就是mcache
,mcentral
和mheap
进来的地方。
mcache
是各种大小的预分配块列表,mcache
每个处理器P一个。由于P一次运行一个 goroutine G,因此分配mcache
不需要锁定。如果
mcache
用完预分配的块,则请求更多块,这些块在Pmcentral
之间共享。如果
mcentral
用完,则会请求更多块,mheap
而这些块又可能会向操作系统请求更多内存。如果请求的块足够大,则直接从
mheap
.
所有这一切的重点是避免在小内存分配期间锁定。但是从 获得的所有内存部分mcache
,mcentral
并且mheap
是堆的一部分,无论在哪个P上运行,它们都可以被G使用,并且在不再使用时必须进行垃圾回收。
- 1 回答
- 0 关注
- 107 浏览
添加回答
举报
0/150
提交
取消