我对Go的栈管理很感兴趣,我搜索了各种数据,但是我很困惑,因为所有的数据都是不同的,我好奇的是,golang的栈管理是栈分裂还是栈复制。正确答案是什么?高朗版本:go1.16.3
nkcskrwz1#
堆栈分割与堆栈复制并不是一种语言特性--language spec没有提到这两种策略--而是语言实现中的一种设计选择,实现有很多种。因此,正如Flimzy在他的评论中指出的,你应该在问题中指定你所指的实现。从Go 1.4开始,“规范的”Go编译器(称为 gc)不再拆分堆栈,现在使用 * 堆栈复制 *:堆栈现在是连续的,在必要时重新分配,而不是在新的“段”上链接;因此,这个版本消除了臭名昭著的“热堆栈分裂”问题。Brad Fitzpatrick(Go团队的前成员)在他的Gophercon India 2016(在mark 12'50'')中解释了堆栈分裂在Go编译器中引起的一些问题:[...]在Go语言中,你有goroutines,它就像一个非常非常轻量级的线程,它有一个很小的堆栈,它会根据需要增长。它过去的工作方式是小goroutines有小堆栈,当你用完堆栈空间时,你会在其他地方创建另一个堆栈,当你调用函数并返回时,你会在这些堆栈之间跳转。这在大多数时候都很棒,直到它不再是,直到你在一个紧密的循环中,比如JPEG解码器之类的,你在堆栈之间跳跃,你会有很大的性能损失,这是我们很惊讶的。然后你会把一些代码移到其他地方,你的性能特征会改变很多。至于 gccgo(Go语言的另一种实现),Ian Lance Taylor解释说它在this 2010 paper(第7.4节)和this 2016 thread中使用了 * 堆栈分割 *;基思兰德尔也提供了一些关于another thread中这种设计选择的见解。
1条答案
按热度按时间nkcskrwz1#
堆栈分割与堆栈复制并不是一种语言特性--language spec没有提到这两种策略--而是语言实现中的一种设计选择,实现有很多种。因此,正如Flimzy在他的评论中指出的,你应该在问题中指定你所指的实现。
从Go 1.4开始,“规范的”Go编译器(称为 gc)不再拆分堆栈,现在使用 * 堆栈复制 *:
堆栈现在是连续的,在必要时重新分配,而不是在新的“段”上链接;因此,这个版本消除了臭名昭著的“热堆栈分裂”问题。
Brad Fitzpatrick(Go团队的前成员)在他的Gophercon India 2016(在mark 12'50'')中解释了堆栈分裂在Go编译器中引起的一些问题:
[...]在Go语言中,你有goroutines,它就像一个非常非常轻量级的线程,它有一个很小的堆栈,它会根据需要增长。它过去的工作方式是小goroutines有小堆栈,当你用完堆栈空间时,你会在其他地方创建另一个堆栈,当你调用函数并返回时,你会在这些堆栈之间跳转。这在大多数时候都很棒,直到它不再是,直到你在一个紧密的循环中,比如JPEG解码器之类的,你在堆栈之间跳跃,你会有很大的性能损失,这是我们很惊讶的。然后你会把一些代码移到其他地方,你的性能特征会改变很多。
至于 gccgo(Go语言的另一种实现),Ian Lance Taylor解释说它在this 2010 paper(第7.4节)和this 2016 thread中使用了 * 堆栈分割 *;基思兰德尔也提供了一些关于another thread中这种设计选择的见解。