当切换到新 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 上执行是不可能的。 我的问题是

  1. g停车时会不会所有数据都复制到G'栈中?
  2. 为什么不在执行G的时候把所有的数据都放在G上?

你的问题存在一个根本性的误解:mcache 不是 堆栈的占位符,它是堆上小分配的捷径。它拥有预先分配的内存块,可以分发给特定的 goroutine,避免锁定。

编译器决定是否必须在堆上分配特定变量。一旦完成,这将永远不会被复制回堆栈

现在的问题是如何尽可能有效地从堆中分配内存。这是 mcachemcentralmheap 发挥作用的地方。

  • mcache 是各种大小的预分配块列表,每个处理器有一个 mcache P。由于 P 一次运行一个 goroutine G,来自 mcache 的分配不需要锁定。
  • 如果 mcache 用完了预分配的块,则会从 mcentral 请求更多,这在 Ps 之间共享。
  • 如果 mcentral 用完,会从 mheap 请求更多的块,这可能反过来从 OS.
  • 请求更多的内存
  • 如果请求的块足够大,则直接从mheap请求。

所有这一切的目的是为了避免在小内存分配期间锁定。但是从mcachemcentralmheap获得的所有内存段都是的一部分,它们可以被使用G 不管它在哪个 P 运行 上,它们在不再使用时必须被垃圾回收。

您可以在以下内容中找到有关 内存分配的更多详细信息: