题记
这是我参与「第五届青训营 」伴学笔记创作活动的第 8天,本文用于记录在青训营的学习笔记和一些心得。
day8 1月22日
本节课程:高性能Go语言发行版优化与落地实践
-
优化
- 内存管理优化
- 编译器优化
-
背景
- 自动内存管理和Go内存管理机制
- 编译器优化的基本问题和思路
-
实践:字节跳动遇到的性能问题以及优化方案
追求极致性能
性能优化是什么?
- 提升软件系统处理能力,减少不必要的消耗,充分发掘计算机算力。
为什么要做性能优化?
- 用户体验:带来用户体验的提升——让刷抖音更丝滑,让双十—购物不再卡顿
- 资源高效利用:降低成本,提高效率——很小的优化乘以海量机器会是显著的性能提升和成本节约
总结
- 性能优化的基本问题
- 性能优化的两个层面
- 性能优化的可维护性
自动内存管理
-
动态内存
- 程序在运行时根据需求动态分配的内存: malloc ( )
-
自动内存管理(垃圾回收):由程序语言的运行时系统回收动态内存
- 避免手动内存管理,专注于实现业务逻辑
- 保证内存使用的正确性和安全性: double-free problem, use-after-free problem
-
三个任务
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
Copying GC:将对象复制到另外的内存空间
Mark-sweep GC:使用free list管理空闲内存
Compact GC:原地整理对象
Go内存管理以及优化
总结
-
Go内存管理-分块
-
Go内存管理—缓存
-
Go对象分配的性能问题
- 分配路径过长
- 小对象居多
-
Balanced GC
- 指针碰撞风格的对象分配
- 实现了copying Gc
- 性能收益
编译器和静态分析
编译器的结构
-
重要的系统软件
- 识别符合语法和非法的程序
- 生成正确且高效的代码
-
分析部分(前端front end)
- 词法分析,生成词素(lexeme)
- 语法分析,生成语法树
- 语义分析,收集类型信息,进行语义检查
- 中间代码生成,生成intermediate representation (IR)
-
综合部分(后端back end)
- 代码优化,机器无关优化,生成优化后的lR
- 代码生成,生成目标代码
我们主要学习编译器后端优化
总结
- 编译器的结构与编译的流程
- 编译器后端优化
- 数据流分析和控制流分析
- 过程内分析和过程间分析
Go编译器优化
-
为什么做编译器优化
- 用户无感知,重新编译即可获得性能收益
- 通用性优化
-
现状
- 采用的优化少
- 编译时间较短,没有进行较复杂的代码分析和优化
-
编译优化的思路
- 场景:面向后端长期执行任务
- Tradeoff:用编译时间换取更高效的机器码
-
Beast mode
- 函数内联
- 逃逸分析
- 默认栈大小调整
- 边界检查消除
- 循环展开
- ..............
课后
- 从业务层和语言运行时层进行优化分别有什么特点?
- 从软件工程的角度出发,为了保证语言 SDK 的可维护性和可拓展性,在进行运行时优化时需要注意什么?
- 自动内存管理技术从大类上分为哪两种,每一种技术的特点以及优缺点有哪些?
- 什么是分代假说?分代 GC 的初衷是为了解决什么样的问题?
- Go 是如何管理和组织内存的?
- 为什么采用 bump-pointer 的方式分配内存会很快?
- 为什么我们需要在编译器优化中进行静态代码分析?
- 函数内联是什么,这项优化的优缺点是什么?
- 什么是逃逸分析?逃逸分析是如何提升代码性能的?