当前位置:网站首页>Go语言逃逸分析全纪录

Go语言逃逸分析全纪录

2022-06-25 22:00:00 _七里香

目录

什么是逃逸分析?

逃逸分析是为了什么?

如何查看逃逸

哪些情况会出现逃逸

1,指针逃逸

2,栈空间不足逃逸

3,动态分配逃逸

4,闭包引用对象逃逸


什么是逃逸分析?

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应该分配到堆上。

原网站

版权声明
本文为[_七里香]所创,转载请带上原文链接,感谢
https://lan6193.blog.csdn.net/article/details/125447807