Go 简述一下 Go 栈空间的扩容缩容过程?详解

扩容流程

为啥会有栈空间扩容

由于当前的 Go 的栈结构使用的是连续栈,并且初始值才 2k 比较小,因此随着函数的调用层级加深,Go 的初始栈空间就可能不够用,不够用的话,就会触发栈空间的扩容。

栈空间扩容啥时会触发

编译器会为函数调用插入运行时检查runtime.morestack,它会在几乎所有的函数调用之前检查当前goroutine 的栈内存是否充足,如果当前栈需要扩容,会调用runtime.newstack 创建新的栈。

而新的栈空间,是旧栈空间大小(通过保存在goroutine中的stack信息里记录的栈区内存边界计算出来的)的两倍,但最大栈空间大小不能超过 maxstacksize ,也就是 1G。

缩容流程

为啥会有栈空间缩容

在函数返回后,对应的栈空间会回收,如果调用栈比较深,那么随着函数一个一个返回,回收的栈空间会越来越多。假设在调用栈最深的时候,整体的栈空间扩容到了 100M,那么随着函数的返回,到某一个函数的时候,100M 的栈空间只有 1M 是实际占用的,内存利用率只有区区的 1% ,实在太浪费了。

栈空间缩容啥时会触发

因此在垃圾回收的时候,有必要检查一下栈空间里内存利用率,当利用率低于 25% 时,就要开始进行缩容,缩容成原来的栈空间的 50%,但同时也不能小于栈空间的原始值即最小值,2KB。

相同点

不管是扩容还是缩容,都是使用 runtime.copystack 函数来开辟新的栈空间,然后将旧栈的数据全部拷贝至新的栈空间,并调整原来指针的指向。

延伸阅读

Go 语言内存管理三部曲(二)解密栈内存管理

教程来源于Github,感谢iswbm大佬的无私奉献,致敬!

技术教程推荐

机器学习40讲 -〔王天一〕

雷蓓蓓的项目管理实战课 -〔雷蓓蓓〕

NLP实战高手课 -〔王然〕

SRE实战手册 -〔赵成〕

实用密码学 -〔范学雷〕

深入C语言和程序运行原理 -〔于航〕

Go进阶 · 分布式爬虫实战 -〔郑建勋〕

手把手教你落地DDD -〔钟敬〕

结构思考力 · 透过结构看问题解决 -〔李忠秋〕