Go语言的栈是分割还是复制?

huangapple go评论82阅读模式
英文:

Is Go's stack split or stack copy?

问题

我对Go语言的堆栈管理很感兴趣。我搜索了各种数据,但由于数据都不同,让我感到困惑。我想知道的是,golang的堆栈管理是堆栈分割还是堆栈复制。

正确的答案是什么?

golang版本:go1.16.3

英文:

I'm interested in Go's stack management. I searched various data but it confuses me because all data is different. What I am curious about is whether golang's stack management is stack splitting or stack copying.

What is the correct answer?

golang version: go1.16.3

答案1

得分: 5

栈分割与栈复制并不是一种语言特性,语言规范中没有提到这两种策略,而是语言实现中的设计选择,有几种不同的实现方式。因此,正如Flimzy在他的评论中指出的那样,你应该在问题中指明你所指的是哪种实现方式。

截至Go 1.4,Go语言的“规范”编译器(称为gc)不再进行栈分割,而是使用栈复制

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

Go团队的前成员Brad Fitzpatrick在他的Gophercon India 2016演讲(在12分50秒处)中解释了栈分割在Go编译器中引起的一些问题:

> [...] 在Go中,你有goroutine,它是一种非常轻量级的线程,具有一个小的栈,根据需要增长。它以前的工作方式是,小的goroutine有小的栈,当你的栈空间用完时,你会在其他地方创建另一个栈,并在调用函数和返回时在这些栈之间跳转。这在大多数情况下都很好,直到有一天不好了,比如在一个紧密循环中,比如JPEG解码器之类的东西,你在不同的栈之间跳转,导致性能损失非常大,这是令人惊讶的。然后你把一些代码移到其他地方,你的性能特征就会发生很大变化。

至于Go语言的另一个实现方式_gccgo_,Ian Lance Taylor在这个2016年的讨论串中解释了它使用的栈分割策略;Keith Randall在另一个讨论串中也提供了一些关于这个设计选择的见解。

英文:

Stack splitting vs. stack copying is not so much a language feature—the language spec makes no mention of either strategy—as it is a design choice in implementations of the language, of which there are several. Therefore, as pointed out by Flimzy in his comment, you should specify which implementation you're referring to in your question.


As of Go 1.4, the "canonical" Go compiler (known as gc) no longer splits stacks and now uses stack copying:

> Stacks are now contiguous, reallocated when necessary rather than
> linking on new "segments"; this release therefore eliminates the
> notorious "hot stack split" problem.

Brad Fitzpatrick (former member of the Go team) explains some of the problems that stack splitting caused in the Go compiler in his Gophercon India 2016 (at mark 12'50''):

> [...] in Go, you have goroutines, which is like a really, really lightweight thread that has a stack that's small and it grows as necessary. The way it used to work is little goroutines with little stacks and, when you ran out of stack space, you would make another stack somewhere else and you would be jumping between these stacks as you called functions and returned. Which was great most of the time until it wasn't, until you were in a tight loop, in something like a JPEG decoder or something, and you were bouncing between stacks and you had really big performance penalties that we're surprising. And then you would move some code somewhere else and your performance characteristics would change a lot.


As for gccgo (an alternative implementation of the Go language), Ian Lance Taylor explains that it uses stack splitting in this 2016 thread; Keith Randall also provides some insight about this design choice in another thread.

huangapple
  • 本文由 发表于 2021年5月23日 20:04:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/67659524.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定