高性能Go语言发行版优化与落地实践 | 青训营笔记

224 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记。

前言

今天学习了Go GC及其改进的Balanced GC、学习了编译优化之控制流和数据流分析,通过内联函数可以生成高效执行的机器码,还可以通过指针逃逸分析来栈分配内存,从而减轻GC压力。

1、性能优化的两个基本问题

性能优化是什么?

减少计算机没必要的消耗,充分发挥计算机的算力,从而提高计算机系统的处理能力。

为什么要做性能优化?

1-用户递延角度:让用户操作更丝滑,操作感觉好;让用户能顺利的进行秒杀活动;让用户的账户安全可靠。

2-开发商角度:减少没必要的运输,和不必要的弯路,从而解决系统资源,资源就是成本!

2、性能优化的两个层面

性能优化层面?

1-业务代码,具体问题具体分析。

2-语言运行时优化,底层逻辑优化,适用于上层大多数业务背景。

image.png

3、性能优化的可维护性

性能优化的原则?

image.png

自动内存管理

1、动态内存与自动内存管理

1-程序在运行时需要手动分配内存和释放内存。不分配就操作所带来的问题?需要考虑内存分配多少?分配了不释放带来的问题?分配了释放多次所带来的问题?

2-程序运行时自动分配内存和自动内存垃圾回收。不需要考虑内存分配问题,专注业务逻辑;内存分配的安全性、合理性都由内存自动管理机制保证。

2、自动内存管理的三个任务

1-为新对象分配内存空间。

2-找到存活对象。

3-回收非存活对象的内存空间。

3、自动内存相关基本概念

1-Mutator:业务线程,分配新对象,修改对象指向管理。

2-Collector: GC线程,找到存活对象,回收死亡对象的内存空间。

3-Serial GC:只有一个Collector线程来GC算法

4-Parallel GC:支持多个Collectors线程同时回收内存的算法。

5-Concurrent GC:mutator(s)和collector(s)可以同时执行,即并发执行。

image.png

image.png

4、如何评价GC算法

1-安全性,不能回收存活对象,这是最基本的要求,必须保证。

2-吞吐率,在非GC上花费的时间,1 - mutator time / total time

3-暂停时间,Stop the World,业务是否感知?

4-内存开销,支持自动内存管理所带来的额外内存开销。

5、GC如何判断存活对象?

1-追踪垃圾回溯,标记可达对象,这些对象就是存活对象。

image.png

image.png

image.png

image.png 2-引用计算,为每个对象设置一个引用计数器,当计数器为0时则为垃圾对象。

image.png

优点:

1-内存回收操作时间被平摊到了程序执行的时间中,如p = null,马上就能回收垃圾。

2-内存管理不需要runtime实现细节。C++ 智能指针(smart pointer)

缺点:

1-引用计数开销较大,需要通过原子操作保证计数的原子性和可见性。

2-无法回收循环引用。

3-内存开销大,每个对象都需要计数。

4-当串行引用链过长时,会发生连续内存回收,就会有很大的暂停感。

6、分代假说处理内存分配与垃圾回收

1-为什么要分代?

很多对象在分配出来之后就不用了,就需要回收。

2-GC年龄

每个对象经历一次GC还是存活对象,年龄+1。

3-分代

把不同年龄的对象放在不同的区域,大年龄的放在一个不经常GC的区域,毕竟该对象一直在用;小年龄放在经常需要GC的区域,毕竟多少对象用了不久就不用了。

4-分代中的年轻代和老年代

年轻代:常规对象分配,由于存活对象少,可以采用coping GC 算法,GC吞吐率自然高。

老年代:一些需要长期使用的对象,由于GC时存活对象肯定很多,可以采用指针标记空闲内存算法,即Mark-Sweep GC

Go内存管理及优化

1、Go内存分配

1-分块,提前将内存分块,为对象在heap上分配内存。

image.png

2-缓存

image.png

2、Go内存管理优化

背景

image.png

image.png

3、Balanced GC

image.png

image.png

编译器和静态分析

1、基本介绍

编译器的结构,

image.png

2、数据流和控制流

1-静态分析:不执行程序代码,分析程序的行为和性质。可从控制流和数据流两个角度来分析。

2-控制流,程序执行的流程

3-数据流,数据在控制流上的传递

image.png

3、过程内和过程间分析

1-过程内分析,仅在函数内部进行分析。

2-过程间分析,考虑函数调用时参数传递和返回值的控制流以及控制流之上的数据流。

3-过程间分析是个问题,

image.png

Go编译器优化

1-为什么做编译器优化?

用户无感知,重现编译即可获得性能收益;优化对各种业务是通用的。

2-编译器优化现状

采用的优化少;编译时间短,没有进行较复杂的代码分析和优化。

3-编译优化思路

面向后端长期执行的任务分析;tradeoff,用编译时间换更高效的机器码执行时间,即久编译,快执行。

4-Beast mode

函数内联;逃逸分析;默认栈大小调整;边界检查消除;循环展开。

1、函数内联

image.png

image.png

内联缺点,

1-函数体变大,导致对cache不太友好。

2-编译生成的Go项目镜像比较大。

注:内联带来的优化大多数情况下都是正向的。

2、Beast mode

image.png

3、逃逸分析

image.png

参考文献

[1] 字节跳动第三届青训营教学内容

[2] 字节跳动第三届青训营张老师推荐文献

image.png