内存管理、编译器优化|青训营笔记

97 阅读3分钟

这是我参加第五届青训营伴学笔记创作活动的第 2 天

day3

性能优化(回顾)

  • 提升软件系统处理能力,减少不必要的消耗
  • 提升用户体验
  • 资源高效利用,减低成本,提高效率

性能优化层面

  • 业务层优化

    • 针对特定场景,具体问题具体分析
    • 容易获得较大性能受益
  • 语言运行时优化

    • 解决通用的性能问题
    • 考虑更多场景
    • Tradeoffs
  • 数据驱动

    • pprof
    • 依靠数据
    • 首先优化最大瓶颈

软件质量

  • 保证接口稳定的时候去改进具体实现
  • 测试用例尽可能覆盖多的场景,便于回归
  • 做文档:什么做了,什么没做
  • 隔离:通过选项控制是否开启优化
  • 可观测性:必要的

一.自动内存管理

垃圾回收机制

  • 避免手动内存管理,专注于实现业务逻辑
  • 保证内存使用的正确性和安全性

三个任务

  • 为新对象分配空间
  • 找到存活对象
  • 回收死亡对象的内存空间

相关概念

  • Mutator

    • 业务线程,分配新对象,修改对象指针关系
  • Collector:GC线程,找到存活对象,回收死亡对象的内存空间

  • Serial GC:只有一个collector

  • Parallel GC:支持多个collectors同时回收的GC算法

  • Concurrent GC:mutator(s)和collector(s)可以同时执行

    • Collectors必须感知对象指向关系的改变

image-20230119112341800

  • GC算法的评价

    • 安全性:基本要求
    • 吞吐率:花在GC上的时间
    • 暂停时间:业务是否感知
    • 内存开销:GC元数据开销
  • 追踪垃圾回收:

    • 指针指向关系不可达对象时,即可回收

      • 标记根对象

      • 标记可达对象

      • 清理不可达对象

        • 1.将存活的对象复制到另外的内存空间
        • 2.将死亡对象的内存标记为可分配
        • 3.移动并整理存活对象
      • 根据对象的生命周期,使用不同的标记和清理策略

      eg:image-20230119113215983

      image-20230119113325523

  • 引用计数

    • 每个对象都有一个与之关联的引用数目
    • 对象存活条件:当且仅当引用数>0

    image-20230119113633894

二.Go内存管理及优化

  • 提前将内存分块
  • 对象分配是分场高平的曹组
  • 小对象占比较高

优化方案 Balanced GC

  • 每个g都绑定一大块内存(1kb),称作goroutine allocation buffer(GAB)

  • GAB用于noscan类型的小对象分配:<128b

  • 使用三个指针维护GAB:base end top

  • Bump pointer(指针碰撞)风格对象分配

    • 无须和其他分配请求互斥
    • 分配动作简单高效

image-20230119215336027

  • GAB对于Go内存管理来说是一个大对象

    • 本质:将多个小对象的分配合并成一次大对象的分配
  • 问题:导致内存被延迟释放

  • 解决方案:移动GAB中存活的对象

image-20230119215800626

三.编译器和静态分析

结构

image-20230119220053763

静态分析

  • 不去执行代码,推导程序的行为,分析程序的性质
  • 控制流(Control flow):程序执行的流程

image-20230119220230359

  • 数据流(Data flow):数据在控制流上的传递

过程内和过程间分析

  • 过程内分析:

    • 仅在函数内部进行分析
  • 过程间分析

    • 考虑函数调用时参数传递和返回值的数据流和控制流

image-20230119220621532

四.Go编译器优化

函数内联(Inlining)

  • 将被调用的函数的函数体(callee)的副本替换到调用位置(caller)上,同时重写代码以反映参数的绑定

  • 优点:

    • 消除函数调用开销,例如传递参数,保存寄存器等
    • 将过程间分析转化为过程内分析,帮助其他优化,例如逃逸分析
  • 缺点:

    • 函数体变大,instruction cache不友好
    • 编译生成的Go镜像变大
  • Beast Mode

image-20230119221309776

逃逸分析

  • 分析代码中指针的动态作用域:指针在何处可以被访问

image-20230119221531546