• 逃逸分析


    逃逸分析的好处:

    1 逃逸分析的好处是为了减少gc的压力,不逃逸的对象分配在栈上,当函数返回时就回收了资源,不需要gc标记清除。

    2 逃逸分析完后可以确定哪些变量可以分配在栈上,栈的分配比堆快,性能好(逃逸的局部变量会在堆上分配 ,而没有发生逃逸的则有编译器在栈上分配)。

    3 同步消除,如果你定义的对象的方法上有同步锁,但在运行时,却只有一个线程在访问,此时逃逸分析后的机器码,会去掉同步锁运行。

    四种情况会逃逸:1 函数内new后,返回指针  2 空间不足,如用make函数申请的空间过大,会分配到堆上,3 类型不确定 a 赋值给接口类型,b make申请的空间大小不确定,  4 闭包内的变量,

    参考:https://driverzhang.github.io/post/golang%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E9%80%83%E9%80%B8%E5%88%86%E6%9E%90/

    1 编译原理中,分析指针动态范围的方法称之为逃逸分析,Go语言的逃逸分析是编译器执行静态代码分析后,对内存管理进行的优化和简化,它可以决定一个变量是分配到堆还栈上。

    go在编译的时候进行逃逸分析,来决定一个对象放栈上还是放堆上,不逃逸的对象放栈上,可能逃逸的放堆上。

    编译器会根据变量是否被外部引用来决定是否逃逸:如果在函数外面没有引用到,则优先放到栈区中;如果在函数外面存在引用的可能,则就会放到堆区中;

    //1 将变量取地址返回
    //func test() *User{
    //    a := User{}
    //    return &a
    //}
    
    //// 当输入的变量或指针,直接返回时,不会逃逸,
    //type S struct {}
    //func main() {
    //    var x S
    //    y := &x
    //    _ = fun1(y)
    //    _ = fun2(x)
    //}
    //// 输入直接当成返回值了,因为没有对z作引用,所以z没有逃逸
    //func fun1(z *S) *S {
    //    return z
    //}
    //func fun2(k S) S {
    //    return k
    //}
    
    
    //// z是对x的拷贝,ref函数中对z取了引用,所以z不能放在栈上,
    //// 否则在ref函数之外,通过引用如何找到z,所以z必须要逃逸到堆上
    //package main
    //type S struct {}
    //func main() {
    //    var x S
    //    _ = *ref(x)
    //}
    //func ref(z S) *S {
    //    return &z
    //}
    
    
    // refStruct函数对y取了引用,所以y发生了逃逸,z没有逃逸,
    type S struct {
        M *int
    }
    func main() {
        var i int
        i = 2
        refStruct(i)
    }
    // z不会逃逸,因为z是普通变量,返回z的时候是值拷贝,
    func refStruct(y int) (z S) {
        z.M = &y
        return z
    }
    // 这里的z会逃逸,因为返回的是指针,且z是内部开辟的内存,
    //func refStruct(y int) (z *S) {
    //    z = new(S)
    //    z.M = &y
    //    return z
    //}
    
    
    // 这里的y没有逃逸,z也没有逃逸,
    //type S struct {
    //    M *int
    //}
    //func main() {
    //    var i int
    //    refStruct(&i)
    //}
    //func refStruct(y *int) (z S) {
    //    z.M = y
    //    return z
    //}
    
    ////3 被指针类型的slice、map和chan引用的指针,注意必须是指针,一定发生逃逸
    //func main() {
    //    a := make([]*int,1)
    //    b := 12
    //    a[0] = &b
    //
    //    c := make(map[string]*int)
    //    d := 14
    //    c["aaa"]=&d
    //
    //    e := make(chan *int,1)
    //    f := 15
    //    e <- &f
    //}
    View Code

    参考:https://mp.weixin.qq.com/s?__biz=Mzg3NDUxNDg4Mw==&mid=100000184&idx=1&sn=1f2ce0d8a9c522b6d9a4a581a76adee1&chksm=4eced11479b95802ea205a569789efca7c59cd6b475ddbe8b2378904da893d0eede0210eb283#rd

    https://blog.csdn.net/dianfu2892/article/details/101467101

  • 相关阅读:
    window下eclipse4.5+hadoop2.6.1开发环境配置
    sqoop1.4.6从mysql导入hdfshivehbase实例
    sqoop1.9.7安装和使用
    sqoop1.4.6导出oracle实例
    sqoop1.4.6配置安装
    java 操作hbase1.2
    hbase-1.2.5完全分布式部署
    hadoop2.6环境中部署hive1.2.2的错误
    hive 创建表和导入数据实例
    hive1.2.2部署
  • 原文地址:https://www.cnblogs.com/xxswkl/p/14229446.html
Copyright © 2020-2023  润新知