//为避免浪费时间,请尽快退出
内存管理
测试工具 Benchmark
支持基准性能测试 go test xxx -benchmen
slice
- slice 预分配内存 尽可能在使用 make()初始化切片时提供容量信息
- 大内存未释放 在已有切片基础上创建切片,不会创建新的底层数组 会复用原来切片的底层数组
- 场景
- 原切片较大,代码在原切片基础上新建小切片
- 原底层数组在内存中有引用得不到释放
- 可用 copy 替代 re-slice
map
- 预分配内存
- 不断向 map 中添加元素会触发扩容
- 减少内存拷贝和 rehash 的消耗
字符串处理
拼接效率: strings. Buffer>strings. Builder bytes. Buffer>+
- 字符串在 go 语言中是不可变类型,占用内存大小固定
- +每次回重新分配内存
- bytes. Buffer,strings. Builder 底层是[]byte 数组,不需要每次重新分配内存
空结构体
节约内存
- 空结构体 struct{}实例不占据任何的内存空间
- 作为占位符使用
- 节省资源
- 本身具有很强语义
atomic 包
- 锁的实现是通过操作系统,属于系统调用
- atomic 操作是通过硬件实现,效率比锁高
- sync. Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
- 对于非数值操作,可以使用 atomic. Value,能承载一个 interface{}
性能分析工具 pprof
用于可视化和分析性能分析数据的工具 go tool pprof -http=: 8080 "\http://localhost: 6060/debug/pprof/xxxx"
CPU
falt 当前函数本身的执行耗时 cum 当前函数本身加上其调用函数的总耗时
- Flat==Cum, 函数中没有调用其他函数
- Flat==0, 函数中只有其他函数的调用
命令:topN 功能:查看占用资源最多的函数
命令:list 功能:根据指定的正则表达式查找代码行
命令:web 功能:调用关系可视化
Heap-堆内存
goroutine-协程
goroutine 泄露会导致内存泄漏
mutex-锁
block-阻塞
threadcreate-线程创建
业务服务优化
流程
- 建立服务性能评估手段
- 分析性能数据,定位性能瓶颈
- 重点优化项改造
- 正确性是基础
- 响应数据 diff
- 线上请求数据录制回放
- 新旧逻辑接口数据 diff(差异)
- 优化效果验证
自动内存管理
- 动态内存
- 程序在运行时根据需求动态分配内存:malloc ()
- 自动内存管理(垃圾回收):由程序语言的运行时系统管理动态内存
- 避免手动内存管理,专注于实现业务逻辑
- 保证内存使用的正确性和安全性:避免double-free probledm, use-after-free problem
- 三个任务
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
相关概念
Mutator:业务线程,分配新对象,修改对象指向关系 Collector:GC 线程,找到存活对象,回收死亡对象的内存空间 Serial GC:只有 collector Parallel GC:支持多个 collectors 同时回收的 GC 算法 Concurrent GC:mutator (s)和 collector (s)可以同时执行
垃圾回收
- 对象被回收条件:指针指向关系不可达的对象
- 标记根对象
- 静态变量,全局变量,常量,线程栈
- 标记:找到可达对象
- 求指针指向关系的传递闭包:从根对象出发,找到所有可达对象
- 清理:所有不可达对象
- 将存活对象复制到另外的内存空间
- 将死亡对象的内存标记为可分配
- 移动并整理存活对象
- 根据对象的生命周期,使用不同的标记和清理策略
内存分配
分块
目标:为对象在 heap 上分配内存 提前将内存分块,根据对象大小选择合适块
- mmap()申请内存
- 将内存划分成大块,mspan
- 划分成特定大小小块
noscan mspan:分配不包含指针的对象——GC 不需要扫描 scan mspan:分配包含指针的对象——GC 需要扫描
缓存
g->m->p->mcache 用于快速分配,为绑定于 p
上的 g 分配对象
memory block<-mspan
当 mcache 中的 mspan 分配完毕,向 mcentral 申请带有未分配块的 mspan
当 mspan 中没有分配对象,mspan 会被缓存在 mcentral 中,而不是立即释放。
Balanced GC
本质:将多个小对象的分配合并成一个大对象的分配
问题:GAB 的对象分配方式会导致内存被延迟释放
解决方案:移动 GAB 中存活的对象
- 当总大小超过一定阈值时,将 GAB 存活对象复制到另外分配的 GAB 中
- 原先的 GAB 可以释放
- 本质:copying GC 管理小对象