golang 内存逃逸

golang中的内存分配有栈(stack) 和堆(heap)
  1. 栈分配: 分配速度快,只需要CPU的两个指令,PUSH【分配】和 RELEASE【释放】
  2. 堆分配: 分配速度较慢,首先需要找到一块大小合适的内存块,之后还需要GC垃圾回收才能释放
golang中常见的内存逃逸场景

-gcflags "-m -l" 查看变量逃逸

  1. 函数内部将局部变量指针返回,被外部调用,其生命周期大于栈,溢出
	type User struct {}
	func NewUser() *User{
		return &User{}
	}
	
	func main(){
		_ = NewUser()
	}
  1. 对象太大,超过栈帧大小
	func main(){
		_ = make([]int,0,1000)
		_ = make([]int,0,100000) // 超出范围,逃逸
	}
  1. 闭包引用逃逸
	func f() func() int{
		a:=1
		return func() int{
			return a
		}
	}
	func main(){
		f()
	}
  1. 动态类型逃逸

因为fmt.Println函数参数类型是interface{},在interface 类型上调用方法都是动态调用的 ---- 方法的实现只能在运行时知道

	func main(){
		a:=1
		fmt.Println("a: ",a)
	}
  1. 在切片上存储指针或带指针的指。比如[]*string,导致切片内容逃逸,其引用值一直在堆上
	func main(){
		ch:=make(chan *string,1)
		ch<-new(string)
	}

如何避免内存逃逸
  1. 对于性能要求比较高且访问频次比较高的函数调用,应该尽量避免使用接口类型
  2. 不要盲目使用变量指针作为参数,虽然减少了复制,但变量逃逸的开销更大
  3. 预先设定好slice长度,避免频繁超出容量,重新分配
# golang 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×