美文网首页
Go 语言逃逸分析(版本1.18.2)

Go 语言逃逸分析(版本1.18.2)

作者: Sun东辉 | 来源:发表于2022-05-15 10:25 被阅读0次

    什么是逃逸分析?

    逃逸分析(escape analysis)就是在程序编译阶段根据程序代码中的数据流,对代码中哪些变量需要在栈上分配,哪些变量需要在堆上分配进行静态分析的方法。一个理想的逃逸分析算法自然是能将那些人们认为需要分配在栈上的变量尽可能保留在栈上,尽可能少的“逃逸”到堆上的算法。

    原理

    两个原则:防止迷途指针。

    1. 栈对象的指针不能被分配到堆上;
    2. 栈对象的指针的生命周期,不能比栈对象的生命周期长;

    数据流构建思路:AST树的静态数据流分析(static data-flow analysis)。

    1. 通过 AST 树构造一个有向加权图(权重 = 引用解析次数 - 取地址次数)。
    2. 遍历这个有向加权图,寻找可能违反上述两个原则的赋值路径。如果对象 v 的地址存储在堆中或其他可能比它生命周期长的地方,那么对象 v 就被标记为需要分配到堆上。

    数据结构

    ```go
    // An escape holds state specific to a single function being analyzed
    // within a batch.
    type escape struct {
        *batch
    
        curfn *ir.Func // function being analyzed
    
        labels map[*types.Sym]labelState // known labels
    
        // loopDepth counts the current loop nesting depth within
        // curfn. It increments within each "for" loop and at each
        // label with a corresponding backwards "goto" (i.e.,
        // unstructured loop).
        loopDepth int
    }
    
    ```
    

    实现

    1. 构造顶点 initFunc
      遍历所有函数的局部变量,检查变量的大小,大对象直接标记。
    2. 构造边 walkFunc
      对目标函数的所有语句递归遍历并进行分析,如果语句中存在赋值关系,则为其创建有向边。
    3. 分析有向加权图
      基于生命周期的判断 outlives
      基于权重的判断 walkOne
    4. 遍历顶点,收集被标记的的逃逸原因 walkAll
      编译器内部通过两个 LIFO Queue 来实现该双重循环。
      在遍历的过程中,会同步分析有向权图,即 for len(todo) > 0 {... b.walkOne(root, walkgen, enqueue)}

    相关文章

      网友评论

          本文标题:Go 语言逃逸分析(版本1.18.2)

          本文链接:https://www.haomeiwen.com/subject/rcfuurtx.html