go语言内存逃逸分析

前言

所谓逃逸分析就是指由编译器决定内存分配的位置,不需要程序员指定。函数中申请一个新的对象

1.如果分配在栈中,则函数执行结束可自动将内存回收;

2.如果分配在堆中,则函数执行结束可交给GC处理;

逃逸策略

每当函数中申请新的对象,编译器会根据该对象是否被函数外部引用来决定是否逃逸:

1.如果函数外部没有引用,则优先放到栈中;

2.如果函数外部存在引用,则必定放到堆中;

注意点:对于函数外部不存在引用的对象,也有可能放到堆中,比如内存过大超过栈的存储能力。

逃逸场景

指针逃逸

package main

type Student struct {
    Name string
    Age  int
}

func StudentRegister(name string, age int) *Student {
    s := new(Student) //局部变量s逃逸到堆

    s.Name = name
    s.Age = age

    return s
}

func main() {
    StudentRegister("Jim", 18)
}

函数中的s为局部变量,其值通过函数返回值返回,s是一个指针,其指向的内存地址不会是栈堆

栈空间不足逃逸

package main

func Slice() {
    s := make([]int, 10000, 10000)

    for index, _ := range s {
        s[index] = index
    }
}

func main() {
    Slice()
}

切片空间较大,栈空间不足以存放当前对象时或无法判断当前切片长度是将对象分配到对堆中

动态类型逃逸

很多函数参数为interface类型,比如fmt.println(a ....interface{}),编译期间很难确定其参数的具体类型,也会产生逃逸。

package main

import "fmt"

func main() {
    s := "Escape"
    fmt.Println(s)
}

上述代码s变量只是一个string类型变量,调用fmt.Println()时会产生逃逸

闭包引用对象逃逸

package main

import "fmt"

func Fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}

func main() {
    f := Fibonacci()

    for i := 0; i < 10; i++ {
        fmt.Printf("Fibonacci: %d\n", f())
    }
}

函数中原本属于局部变量的 a,b 由于闭包的引用,不得不将二者放到堆上,以至产生逃逸;

逃逸总结

栈上分配内存比在堆中分配内存有更高的效率

栈上分配的内存不需要GC处理

堆上分配的内存在使用完毕会交给GC处理

逃逸分析目的是决定内存分配地址是栈还是堆

逃逸分析在编译阶段完成

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值