关于内存管理:简单聊聊内存逃逸-|-剑指-offer-golang

问题

简略讲讲golang的内存逃逸吗?

解析

什么是内存逃逸

在程序中,每个函数块都会有本人的内存区域用来存本人的局部变量(内存占用少)、返回地址、返回值之类的数据,这一块内存区域有特定的构造和寻址形式,寻址起来十分迅速,开销很少。这一块内存地址称为栈。栈是线程级别的,大小在创立的时候曾经确定,当变量太大的时候,会”逃逸”到堆上,这种景象称为内存逃逸。简略来说,局部变量通过堆调配和回收,就叫内存逃逸。

内存逃逸的危害

堆是一块没有特定构造,也没有固定大小的内存区域,能够依据须要进行调整。全局变量,内存占用较大的局部变量,函数调用完结后不能立即回收的局部变量都会存在堆外面。变量在堆上的调配和回收都比在栈上开销大的多。对于 go 这种带 GC 的语言来说,会减少 gc 压力,同时也容易造成内存碎片。

如何分析程序是否产生内存逃逸

build时增加-gcflags=-m 选项可剖析内存逃逸状况,比方输入./main.go:3:6: moved to heap: x 示意局部变量x逃逸到了堆上。

内存逃逸产生机会

  • channel 发送指针数据。因为在编译时,不晓得channel中的数据会被哪个 goroutine 接管,因而编译器没法晓得变量什么时候才会被开释,因而只能放入堆中。
package main
func main() {
    ch := make(chan int, 1)
    x := 5
    ch <- x  // x不产生逃逸,因为只是复制的值
    ch1 := make(chan *int, 1)
    y := 5
    py := &y
    ch1 <- py  // y逃逸,因为y地址传入了chan中,编译时无奈确定什么时候会被接管,所以也无奈在函数返回后回收y
}
  • 局部变量在函数调用完结后还被其余中央应用,比方函数返回局部变量指针或闭包中援用包外的值。因为变量的生命周期可能会超过函数周期,因而只能放入堆中。
package main

func Foo () func (){
    x := 5            // x产生逃逸,因为在Foo调用实现后,被闭包函数用到,还不能回收,只能放到堆上寄存
    return func () {
        x += 1
    }
}
func main() {
    inner := Foo()
    inner()
}
  • 在 slice 或 map 中存储指针。比方 []*string,其前面的数组可能是在栈上调配的,但其援用的值还是在堆上。
package main
func main() {
    var x int
    x = 10
    var ls []*int
    ls = append(ls, &x)        // x产生逃逸,ls存储的是指针,所以ls底层的数组尽管在栈存储,但x自身却是逃逸到堆上
}
  • 切片扩容后长度太大,导致栈空间有余,逃逸到堆上。
package main

func main() {
    s := make([]int, 10000, 10000)
    for index, _ := range s {
        s[index] = index
    }
}
  • 在 interface 类型上调用办法。 在 interface 类型上调用办法时会把interface变量应用堆调配, 因为办法的真正实现只能在运行时晓得。
package main
type foo interface {
    fooFunc()
}
type foo1 struct{}
func (f1 foo1) fooFunc() {}
func main() {
    var f foo
    f = foo1{}
    f.fooFunc()   // 调用办法时,f产生逃逸,因为办法是动态分配的
}

防止内存逃逸的方法

  • 对于小型的数据,应用传值而不是传指针,防止内存逃逸。
  • 防止应用长度不固定的slice切片,在编译期无奈确定切片长度,只能将切片应用堆调配。
  • interface调用办法会产生内存逃逸,在热点代码片段,审慎应用。

写在最初

喜爱本文的敌人,欢送关注公众号「会玩 code」,专一大白话分享实用技术。

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据