这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天
前言
- 上节课:高质量编程与性能调优
- 高质量编程:
- 编码规范:写出高性能、可维护的代码
- 性能优化建议
- 性能优化
- 分析工具——pprof:采样原理、如何定位性能问题等等
- 业务优化
- 基础库优化
- Go语言优化
本节课:高性能Go语言优化与落地实践- 优化
-
- 内存管理优化
-
- 编译器优化
- 背景
-
- 自动化内存管理和Go内存管理机制
-
- 编译器优化的基本问题和思路
1.自动内存管理
动态内存
- 程序在运行时根据需求动态分配的内存: malloc()
自动内存管理(垃圾回收) :由程序语言的运行时系统管理动态内存
- 避免手动内存管理,专注于实现业务逻辑
- 保证内存使用的
正确性和安全性: double -free problem, use- after-free problem
三个任务
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
1.1 自动内存管理
● Mutator:业务线程,分配新对象,修改对象指向关系
● Collector: GC线程,找到存活对象,回收死亡对象的内存空间
● Serial GC:只有一个collector
● Parallel GC:支持多个collectors同时回收的GC算法
●Concurrent GC: mutator(s)和collector(s)可以同时执行
Collectors必须感知对象指向关系的改变!
2.1 评价GC算法
安全性(Safety):不能回收存活的对象基本要求
-
吞吐率(Throughput): 1
花在GC.上的时间 -
暂停时间(Pause time): stop the world (STW)
业务是否感知 -
内存开销(Space overhead)
GC元数据开销
追踪垃圾回收(Tracing garbage collection)
引用计数(Reference counting)
2.Go内存管理及优化
2.1Go内存分配 目标:为对象在heap.上分配内存
提前将内存分块
- 调用系统调用mmap()向OS申请一大块内存, 例如4 MB
- 先将内存划分成大块,例如8 KB,称作mspan
- 再将大块继续划分成特定大小的小块,用于对象分配
- noscan mspan:分配不包含指针的对象 GC不需要扫描
- scan mspan:分配包含指针的对象 GC需要扫描
对象分配:根据对象的大小,选择最合适的块返回
2.2Go内存管理优化
对象分配是非常高频的操作:每秒分配GB级别的内存
小对象占比较高
Go内存分配比较耗时
●分配路径长: g -> m-> p-> mcache -> mspan -> memory block -> return pointer
●pprof:对象分配的函数是最频繁调用的函数之-
2.3 Balanced GC ●GAB对于Go内存管理来说是一个对象
●本质:将多个小对象的分配合并成一次达对象的分配
●问题: GAB的对象分配方式会导致内存被延迟释放
方案:移动GAB中存活的对象
·当GAB总大小超过一定阈值时, 将GAB中存活的对象复制到另外分配的GAB中
·原先的GAB可以释放,避免内存泄漏
·本质:
用copying GC的算法管理小对象。根据对象的生命周期,使用不同的标记和清理策略