x高性能Go语言发行版优化与落地实践

本节课主要内容

  • 优化

    内存管理优化

    编译器优化

  • 背景

    自动内存管理和Go内存管理

    编译器优化

性能优化是什么?

提升软件系统处理能力,减少不必要消耗

为什么做性能优化?

用户体验、资源的高效利用

怎么做优化?

  • 业务层优化
  • 语言运行时优化

总结:

  • 性能优化的基本问题
  • 性能优化的两个层面
  • 性能优化的可维护性

一、自动内存管理

1、自动内存管理

  • 动态内存

    程序运行时内存的动态分配:malloc()

  • 自动内存管理

    避免手动内存管理

    保证内存的使用的正确性和安全性:double-free-problem 和 use-after-free problem

相关概念

  • Mutator

    业务线程,分配新的对象,修改对象的指向关系

  • Collector

    GC线程,找到存活对象,回收死亡对象

  • Serial GC

    只有一个collector

  • Parallel GC

    支持多个collector

  • Concurrent GC

    业务线程和GC线程同时执行,必须感知对象指向关系的改变

  • 评价GC 算法

    安全性(Safety):不能回收存活的对象 基本要求

    吞吐率(Throughput):花在GC上的时间

    暂停时间(Pause time):stop the world(STW)业务是否感知

    内存开销 (Space overhead)GC 元数据开销

  • 追踪垃圾回收(Tracing garbage collection)

  • 引用计数(Reference counting)

2、追踪垃圾回收

回收条件:指针指向关系不可达

标记根对象:静态变量、全局变量、常量、线程栈

标记:找到可达对象

  • 求指针指向关系的传递闭包:从根对象出发,找到所有可达对象

清理:所有不可达对象

  • Copying GC
  • Mark-Sweep GC
  • Mark-Compact GC

根据对象的生命周期选择不同的标记清理策略

3、分代GC(Generational GC)

  • 分代假说 (Generational hypothesis): most objects die young

  • Intuition:很多对象在分配出来后很快就不再使用了

  • 每个对象都有年龄:经历过 GC 的次数

  • 目的:针对年轻和老年的对象,制定不同的 GC 策路,降低整体内存管理的开销,不同年龄的对象处于 heap的不同区域

  • 年轻代 (Young generation)

    常规的对象分配

    由于存活对象很少,可以采用 copying collection

    GC 吞吐率很高

  • 老年代 (Old generation)

    对象趋向于一直活着,反复复制开销较大

    可以采用 mark-sweep collection

4、引用计数

  • 每个对象都有一个与之关联的引用数目

  • 对象存活的条件:当且仅当引用数大于 0

  • 优点

    内存管理的操作被平雄到程序执行过程中

    内存管理不需要了解runtime 的实现细节:C++ 智能指针 (smart pointer)

  • 缺点

    维护引用计数的开销较大:通过原子操作保证对引用计数操作的原子性和可见性
    无法回收环形数据结构—weak reference
    内存开销:每个对象都引1入的额外内存空间存储引用数目
    回收内存时依然可能引发暂停

5、总结

  • 背景和意义
  • 概念和评价方法
  • 追踪垃圾回收
  • 引用回收
  • 分代GC

二、Go内存管理

1、Go内存分配

三、编译器和静态分析

四、Go编译器优化