Go中协程栈不够大怎么办?逃逸分析和栈扩容

1. 协程栈不够用的原因?

协程栈的初始空间为2K-4K。协程栈不够用的原因主要有两点:

  1. 局部变量太大:局部变量储存在栈中,太大的局部变量会造成栈空间被占满
  2. 栈帧太多:协程调用的函数过多,没有返回值的递归,会很快的将内存占满。

2. 解决办法

2.1 逃逸分析(用于解决局部变量大)

逃逸分析是指变量从栈上逃逸到队内存上,在堆上分配内存。在编译阶段确定变量是分配在栈上还是分配在堆上。
(1)逃逸分析的原因及作用
在Go语言中一个变量是在堆上分配,还是在栈上分配,是经过编译器的逃逸分析之后得出的”结论“,逃逸分析可以把那些不需要分配到堆上的变量分配到栈上,可以减轻内存分配的开销(分配在栈上的开销比分配在堆上的开销要小得多),同时可以减少垃圾回收的压力,提高程序运行速度。
(2)逃逸分析的情况(附上代码)
逃逸分析主要可以分为三种情况:

  1. 指针逃逸:在函数中返回了局部变量的指针,并且该指针在函数的外部存在引用。
  2. 空接口逃逸:函数的参数中使用了空接口,函数的参数可能会发生逃逸,主要时因为空接口作为参数很可能发生反射,反射必须在堆上进行。
  3. 大变量逃逸:超过64KB的变量会发生逃逸。
    1.指针逃逸
    指针逃逸
    2.空接口逃逸
    空接口逃逸
    Println源码
    由于fmt.Println传入的参数为空接口,所以参数i可能会发生空接口逃逸。

2.2 栈扩容(用于解决栈帧太多)

在Go语言1.13版本前,采用的栈扩容机制是分段扩容,在Go语言的1.13版本后采用的扩容机制为连续扩容
1.分段扩容
分段栈扩容
分段栈是在帧空间的下方开辟一段连续的空间,用来存放扩容的栈空间,并通过指针相连。
**优点:**不浪费空间,缺点是栈指针会在不连续的栈空间俩回切换造成性能下降。

2.连续栈
连续栈扩容
在Go语言的1.13版本后都采用连续栈扩容,连续栈扩容会给栈空间不够的协程开辟一段新的内存空间,将旧的协程拷贝到新的较大的空间中。**空间不足的时候扩容为原来的两倍,空间使用率不足四分之一的时候缩容到原来的一半。**优点:空间一直是连续的,减少了不连续的指针跳转问题,缺点是:扩容伸缩时候开销大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值