Go 的堆栈是拆分还是堆栈复制?

时间:2021-05-23 12:04:05

标签: go stack

我对 Go 的堆栈管理感兴趣。我搜索了各种数据,但它让我感到困惑,因为所有数据都不同。我比较好奇的是golang的栈管理到底是栈拆分还是栈复制。

正确答案是什么?

golang 版本:go1.16.3

1 个答案:

答案 0 :(得分:5)

堆栈拆分与堆栈复制与其说是一种语言特性——language spec 都没有提到任何一种策略——因为它是语言的实现中的一种设计选择,其中有几个。因此,正如 Flimzy 在 his comment 中指出的那样,您应该指定您在问题中所指的实现。

Go 1.4 开始,“规范的”Go 编译器(称为 gc)不再拆分堆栈,现在使用堆栈复制

<块引用>

堆栈现在是连续的,必要时重新分配而不是 链接新的“段”;因此,此版本消除了 臭名昭著的“热堆栈拆分”问题。

Brad Fitzpatrick 在他的 Gophercon India 2016 中解释了 Go 编译器中堆栈拆分导致的一些问题(见 mark 12'50''):

<块引用>

[...] 在 Go 中,你有 goroutines,它就像一个非常非常轻量级的线程,它有一个很小的堆栈,并且可以根据需要增长。它过去的工作方式是使用小堆栈的小 goroutine,当你用完堆栈空间时,你会在其他地方创建另一个堆栈,当你调用函数并返回时,你会在这些堆栈之间跳转。大多数时候这很好,直到它不是,直到你处于一个紧密循环中,在像 JPEG 解码器之类的东西中,并且你在堆栈之间弹跳并且你有非常大的性能损失,我们感到惊讶。然后你会将一些代码移到其他地方,你的性能特征会发生很大变化。

但是,根据 Ian Lance Taylor 在 this 2016 thread 中的帖子,gccgo(gc 的替代编译器)使用了堆栈拆分。基思·兰德尔 (Keith Randall) 在 another thread 中提供了有关此设计选择的一些见解。