编译器与内存管理 | 青训营笔记

71 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

详细知识点介绍

  • 垃圾回收
  • 堆空间的分配
  • 代码静态分析

自动内存管理

  自动内存管理的一些相关概念如下:

  • Mutator:业务线程
  • Collector: GC 线程
  • Serial GC:只有一个 collector
  • Parallel GC:支持多个 collector 同时运行的 GC 算法
  • Concurrent GC: mutator 和 collector 可同时运行的 GC 算法

  评价一个 GC 算法的好坏,主要在以下几点:

  • 安全性(Safety):不能回收存活的对象

  • 吞吐率(Throughput):

    1GC时间程序总执行时间1-\frac{GC时间}{程序总执行时间}
  • 暂停时间(Pause Time):Stop The World(STW)

  常见的垃圾回收思路有追踪垃圾回收和引用计数。追踪垃圾回收的步骤包括标记根对象->标记可达对象(求指针指向关系的传递闭包)->清理不可达对象;引用计数的中心思想是记录每个对象所关联的指针数目(指向该对象的指针数目),当其降为0时即可清理该对象(这让我想到了 Linux 中ls -l看到的链接数)。和追踪垃圾回收相比,引用计数有内存管理过程平摊、实现简单等优点,但也有开销大、清理不彻底(如环状引用)等缺点。

  在追踪垃圾回收清理中,清理不可达对象的方式包括:

  • 将存活对象复制到另外的内存中(Copying GC)
  • 将死亡对象的内存标记为“可分配”(Mark-Sweep GC)
  • 移动整理存活对象(Mark-Compact GC)

Go 的内存分配

  Go 的 heap 空间的分配过程大致如下:

  • 调用系统调用mmap()向操作系统申请一块内存
  • 将这块内存分割为大块
  • 将大块分为特定大小的小块
  • 对于含有指针的对象,进行 scan mspan;反之进行 noscan mspan。

  Go

静态分析

  GoLang 代码编译的大致过程如下:

  • 词法分析:生成词素(lexeme)
  • 语法分析:生成语法树
  • 语义分析:生成类型信息、语义检查
  • 中间代码分析:生成与平台无关的 Intermediate Representation (IR)
  • 代码优化:对 IR 进行与平台无关的优化
  • 代码生成:生成目标代码

  静态分析是指不执行代码,推导程序行为、分析程序性质。常见的静态分析包括控制流(Control flow)分析(分析程序执行流程)和数据流(Data flow)分析(数据在控制流上的传递)。静态分析有助于简化代码,提高程序运行效率。

  内联(Inline)是指将被调用函数的函数体(callee)的副本替换到被调用的位置上,GoLang编译器默认对简短的函数进行了内联。对简短的函数进行内联可减少函数调用的开销,提高程序运行效率;但是函数内联会增大程序体积、降低 instruction cache 效率。

  逃逸分析是指代码中指针的动态作用域。对于没有逃逸的对象(作用范围在函数内)可直接在 stack 为其分配内存,降低 GC 压力。

本文若有不足之处,欢迎纠正(≧^.^≦)喵~
我的其他笔记,可在掘金或 Github( github.com/DoudiNCer/IWnA )阅读