这是我参与「第五营」笔记创作活动的的第5天。
Golang 性能调优实践
一、简介
⭐ 性能调优原则
- 要依靠数据不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
二、性能分析工具 pprof
⭐ 希望知道应用在什么地方耗费了多少 CPU、Memory
⭐ pprof 是用于可视化和分析性能分析数据的工具
功能简介
- 具体的工具:可以在
runtime/pprof中找到源码,同时Golang的http标准库中也对pprof做了一些封装,能让你在http服务中直接使用它 - 采样部分:它可以采样程序运行时的 CPU、堆内存、goroutine、 锁竞争、阻塞调用和系统线程的使用数据
- 分析:通过网页和可视化终端直观分析
- 展示:用户可以通过列表、调用图、火焰图、源码、反汇编等视图去展示采集到的性能指标。方便分析
排查实战
内容较多,具体内容可以查看这篇博客:golang pprof 实战
采样过程和原理
CPU
⭐ 采样对象: 函数调用和它们占用的时间
⭐ 采样率: 100次/秒,固定值
⭐ 采样时间: 从手动启动到手动结束
⭐ 操作系统:每 10ms 向进程发送一次 SIGPROF 信号
⭐ 进程:每次接收到 SIGPROF 会记录调用堆栈
⭐ 写缓冲:每 100ms 读取已经记录的调用栈并写入输出流
heap-堆内存
- 采样程序通过内存分配器在堆上分配和释放的内存,记录分配/释放的大小和数量
- 采样率:每分配 512KB 记录一次,可在运行开头修改,1为每次分配均记录
- 采样时间:从程序运行开始到采样时
- 采样指标:alloc space, alloc objects, inuse space, inuse_objects
- 计算方式:inuse = alloc - free
Goroutine & ThreadCreate
⭐ Goroutine:记录所有用户发起且在运行中的 goroutine (即入门非runtime开头的) runtime.main 的调用信息
⭐ ThreadCreate:记录程序创建的所有系统线程的信息
Block-阻塞
- 采样阻塞操作的次数和耗时
- 采样率:阻塞耗时超过闯值的才会被记录,1为每次阻塞均记录
Mutex-锁
- 采样争抢锁的次数和耗时
- 采样率:只记录固定比例的锁操作,1为每次加锁均记录
小结
⭐ 掌握常用 pprof 工具功能
⭐ 灵活运用 pprof 工具分析解决性能问题
⭐ 了解 pprof 的采样过程和工作原理
性能调优案例
介绍实际业务服务性能优化的案例,对逻辑相对复杂的程序如何进行性能调优
业务服务优化
基本概念
⭐ 服务: 能单独部署,承载一定功能的程序
⭐ 依赖:Service A 的功能实现依赖,Service B 的响应结果,称为 Service A 依赖 Service B
⭐ 调用链路:能支持一个接口请求的相关服务集合及其相互之间的依赖关系
⭐ 基础库: 公共的工具包、中间件
流程
- 建立服务性能评估手段
服务性能评估方式
- 单独
benchmark无法满足复杂逻辑分析- 不同负载情况下性能表现差异 请求流量构造
- 不同请求参数覆盖逻辑不同
- 线上真实流量情况
压测范围
- 单机器压测
- 集群压测
性能数据采集
- 单机性能数据
- 集群性能数据
- 分析性能数据,定位性能瓶颈
使用库不规范
高并发场景优化不足
- 重点优化项改造
正确性是基础
响应数据 diff
- 线上请求数据录制回放
- 新旧逻辑接口数据 diff
- 优化效果验证
重复压测验证
上线评估优化效果
- 关注服务监控
- 逐步放量
- 收集性能数据
基础库优化
⭐ AB实验SDK的优化
分析基础库核心逻辑和性能瓶颈
- 设计完善改造方案
- 数据按需获取
- 数据序列化协议优化
内部压测验证
推广业务服务落地验证
Go 语言优化
编译器&运行时优化
- 优化内存分配策略
- 优化代码编译流程,生成更高效的程序
- 内部压测验证
- 推广业务服务落地验证
优点
- 接入简单,只需要调整编译配置
- 通用性强
小结
⭐ 性能调优原则
- 要依数据不是猜测
⭐ 性能分析工具 pprof
- 熟练使用 pprof 工具排查性能问题并了解其基本原理
⭐ 性能调优
- 保证正确性
- 定位主要瓶颈