当切换到新 G 时,P 会将 mcache 复制到 G 堆栈吗?
will P copy mcache to G stack when switch to new G?
在Go的GMP(goroutine, system thread, context)模型中,一个goroutine可能会产生很多个对象放在P(堆内存?)中,那么在Park的时候,P上的数据会不会全部复制到G的栈中?如果是这样,G的栈可能会增长到很大,这让P的设计显得毫无意义,但如果不是,调度器如何解决多个G的数据同时存储在P中的问题呢?而如果 G 想在另一个 P 上执行是不可能的。
我的问题是
- g停车时会不会所有数据都复制到G'栈中?
- 为什么不在执行G的时候把所有的数据都放在G上?
你的问题存在一个根本性的误解:mcache
不是 堆栈的占位符,它是堆上小分配的捷径。它拥有预先分配的内存块,可以分发给特定的 goroutine,避免锁定。
编译器决定是否必须在堆上分配特定变量。一旦完成,这将永远不会被复制回堆栈。
现在的问题是如何尽可能有效地从堆中分配内存。这是 mcache
、mcentral
和 mheap
发挥作用的地方。
mcache
是各种大小的预分配块列表,每个处理器有一个 mcache
P。由于 P 一次运行一个 goroutine G,来自 mcache
的分配不需要锁定。
- 如果
mcache
用完了预分配的块,则会从 mcentral
请求更多,这在 Ps 之间共享。
- 如果
mcentral
用完,会从 mheap
请求更多的块,这可能反过来从 OS. 请求更多的内存
- 如果请求的块足够大,则直接从
mheap
请求。
所有这一切的目的是为了避免在小内存分配期间锁定。但是从mcache
、mcentral
和mheap
获得的所有内存段都是堆的一部分,它们可以被使用G 不管它在哪个 P 运行 上,它们在不再使用时必须被垃圾回收。
您可以在以下内容中找到有关 堆 内存分配的更多详细信息:
在Go的GMP(goroutine, system thread, context)模型中,一个goroutine可能会产生很多个对象放在P(堆内存?)中,那么在Park的时候,P上的数据会不会全部复制到G的栈中?如果是这样,G的栈可能会增长到很大,这让P的设计显得毫无意义,但如果不是,调度器如何解决多个G的数据同时存储在P中的问题呢?而如果 G 想在另一个 P 上执行是不可能的。 我的问题是
- g停车时会不会所有数据都复制到G'栈中?
- 为什么不在执行G的时候把所有的数据都放在G上?
你的问题存在一个根本性的误解:mcache
不是 堆栈的占位符,它是堆上小分配的捷径。它拥有预先分配的内存块,可以分发给特定的 goroutine,避免锁定。
编译器决定是否必须在堆上分配特定变量。一旦完成,这将永远不会被复制回堆栈。
现在的问题是如何尽可能有效地从堆中分配内存。这是 mcache
、mcentral
和 mheap
发挥作用的地方。
mcache
是各种大小的预分配块列表,每个处理器有一个mcache
P。由于 P 一次运行一个 goroutine G,来自mcache
的分配不需要锁定。- 如果
mcache
用完了预分配的块,则会从mcentral
请求更多,这在 Ps 之间共享。 - 如果
mcentral
用完,会从mheap
请求更多的块,这可能反过来从 OS. 请求更多的内存
- 如果请求的块足够大,则直接从
mheap
请求。
所有这一切的目的是为了避免在小内存分配期间锁定。但是从mcache
、mcentral
和mheap
获得的所有内存段都是堆的一部分,它们可以被使用G 不管它在哪个 P 运行 上,它们在不再使用时必须被垃圾回收。
您可以在以下内容中找到有关 堆 内存分配的更多详细信息: