当前位置:网站首页>Go语言逃逸分析全纪录
Go语言逃逸分析全纪录
2022-06-25 22:00:00 【_七里香】
目录
什么是逃逸分析?
Go程序为变量分配内存分为两途径:
1,全局的堆空间动态分配内存
2,每个goroutine的栈空间
一般来说开发者并不需要关心内存分配在栈上 or 还是堆上。但从性能的角度出发,在栈上分配内存和在堆上分配内存,性能差异还是非常大的。
在栈上分配和回收内存的开销很低,只需要2个CPU 指令:PUSH、POP。
前者是将数据push到栈空间以完成分配,后者则是释放空间,也就是说在栈上分配内存,消耗的仅是将数据拷贝到内存的时间,而在堆上分配,一个很大的额外开销则是垃圾回收。
在Go中,堆内存通过垃圾回收机制自动管理,Go的垃圾回收采用的是标记清除算法,并且在此基础上使用了三色标记法和写屏障技术,提高了效率。
标记清除算法的一个典型操作是在标记期间,需要STW,即暂停程序(Stop the world),标记结束之后,用户程序才可以继续执行。
堆内存分配导致垃圾回收的开销远大于栈空间分配与释放的开销。
那么 Go编译器怎么知道某个变量需要分配在栈 or 堆上呢?
编译器决定内存分配位置的方式,就称之为逃逸分析(escape analysis)。逃逸分析由编译器完成,作用于编译阶段。
逃逸分析是为了什么?
go在编译的时候会进行逃逸分析,目的是决定一个对象放栈上还是堆上,不逃逸的对象放栈上,可能逃逸的放堆上。
最大的好处是减少gc的压力,不逃逸的对象分配在栈上,当函数返回时就回收了资源,不需要gc标记清除。
因为通过逃逸分析就可以确定哪些变量可以分配在栈上,栈的分配比堆快,性能好。
如何查看逃逸
编译go代码时加
-gcflags "-m -l"
参数即可。
哪些情况会出现逃逸
1,指针逃逸
func f(x, y int) *int {
n := new(int) // new(int) escapes to heap
*n = x * y
return n
}
_ = f(10, 20)
上述代码中在函数结束时返回一个指针,此时进行编译,new(int)就会导致变量n逃逸到堆上。
此时n作为函数f的返回值会在main中继续使用,因此n指向的内存不能分配在栈上,会随着函数结束而被回收。
2,栈空间不足逃逸
_ = make([]int, 1000, 8191) // make([]int, 1000, 8191) does not escape 此时<64KB (int占用8字节)
_ = make([]int, 1000, 8193) // make([]int, 1000, 8193) escapes to heap 此时>64KB
_ = make([]int, 8193) // make([]int, 8193) escapes to heap
_ = make([]int, 1000, 10000) // make([]int, 1000, 10000) escapes to heap
也就是说,你每次make时创建不同的长度,其实编译器都会做不同的处理,不同情况可能会导致开销变大;
当切片占用内存超过一定大小 或无法确定当前切片长度时,其内存将在堆上分配。
其达到多少会逃逸到堆上受操作系统对内核线程栈空间的大小限制。
3,动态分配逃逸
func f1() {
s := 10
_ = make([]int, s) // make([]int, s) escapes to heap
}
f1() // 因为变量s可能被更改,所以编译器认为应该分配到 heap
其它情况比如动态类型,入参为interface{},编译器无法确定到底是什么类型,也会发生逃逸。
就像fmt.Printf(),它的障眼法可不少。
4,闭包引用对象逃逸
Go语言支持闭包机制,如下:
func f2() func() int {
a, b := 1, 2
return func() int { // func literal escapes to heap
return a + b
}
}
f2()
本来a和b作为函数局部变量应该分配到stack中,但是由于f()函数返回了一个闭包函数,该闭包函数访问了外部变量a和b, 此时若函数f2 return,实际a和b还是被引用,无法回收,因此编译器认为a和b应该分配到堆上。
边栏推荐
- . SQL database import error: / *! 40101 SET @OLD_ COLLATION_ [email protected]@COLLATION_ CONNECTION */
- The first public available pytorch version alphafold2 is reproduced, and Columbia University is open source openfold, with more than 1000 stars
- Leetcode(605)——种花问题
- 22 years of a doctor in Huawei
- Actual combat: how to quickly change font color in typera (blog sharing - perfect) -2022.6.25 (solved)
- 【opencv450 samples】创建图像列表yaml
- 【AXI】解读AXI协议原子化访问
- [opencv450 samples] read the image path list and maintain the proportional display
- LM小型可编程控制器软件(基于CoDeSys)笔记十七:pto脉冲功能块
- Oracle - getting started
猜你喜欢
ACM. HJ16 购物单 ●●
CAD中图纸比较功能怎么用
The first public available pytorch version alphafold2 is reproduced, and Columbia University is open source openfold, with more than 1000 stars
Fegin client entry test
2. What is the geometric meaning of a vector multiplying its transpose?
leetcode_ 136_ A number that appears only once
String deformation (string case switching and realization)
Meta universe standard forum established
Idea auto generator generates constructor get/set methods, etc
UE4 学习记录二 给角色添加骨架,皮肤,及运动动画
随机推荐
User interaction scanner usage Advanced Edition example
毕业旅行 | 伦敦5日游行程推荐
ES6 const constants and array deconstruction
Windows安装Redis及简单使用
What aspects should we start with in the feasibility analysis of dry goods?
Set up your own website (15)
[opencv450 samples] create image list yaml
我的vscode
Implementation of importing vscode from PDM
Flex & Bison 开始
RepOptimizer: 其实是RepVGG2
统计字符串中不同回文子序列的个数
1281_ FreeRTOS_ Implementation analysis of vtaskdelayuntil
23class introduction
Rk3568+ Hongmeng industrial control board industrial gateway video gateway solution
Leaky API interface practical development series (13): gooseneck cloud service php-api two-dimensional array parameter transfer solution
No absurd tea applet - rule change
Some points to pay attention to when closing mongodb services (as well as related commands when opening)
#24class静态成员
My C language learning process