性能调优实战案例 | 青训营笔记

90 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

一、pprof 采样过程和原理

1. cpu

🐷 采样对象:函数调用和它们占用的时间

🐷 采样率:100次每秒,固定值

🐷 采样时间:从手动启动到手动结束

image.png

🐷 操作系统:每10秒向进程发送一次SIGPROF信号

🐷 进程:每次接受SIGPROF会记录调用堆栈

🐷 写缓冲:每100毫秒读取已经记录的调用栈并写入输出流

image.png

2. Heap 堆内存

🐷 采样程序通过内存分配器在堆上分配和释放的内存,记录分配/释放的大小和数量

🐷 采样率:每分配512kb记录一次,可在运行开头修改,1为每次分配均记录

🐷 采样时间:从程序运行开始到采样时

🐷 采样指标:alloc_space,alloc_objects,inuse_space,inuse_objects

🐷 计算方式:inuse = alloc-free

3. Gorountine 协程 & ThreadCreae 线程创建

image.png

(1)Goroutine

🐷 记录所有用户发起且在运行中的 gorountine (即入口非runtime开头的) runtime.main 的调用栈信息

(2)threadCreate

🐷 记录程序创建的所有系统线程信息

4. Block & Mutex 锁

image.png

(1)阻塞操作

🐷 采样阻塞操作的次数和耗时

🐷 采样率:阻塞耗时超阈值值的才会被记录,1为每次阻塞均记录

(2)锁竞争

🐷 采样争抢锁的次数和耗时

🐷采样率:只记录固定比例的锁操作,1为每次加锁均记录

二、性能调优案例

1. 业务服务优化

(1)基本概念

🐷 服务:能单独部署,承载一定功能的程序

🐷 依赖: Service A 的功能实现依赖 Service B 的响应结果,称为 Service A 依赖 Service B

🐷 调用链路: 能支持一个接口请求的相关服务集合及其相互之间的依赖关系

🐷 基础库:公共的工具包、中间件

(2)流程

🐷 建立服务性能评估手段

😈 服务性能评估方式
① 单独 benchmark 无法满足复杂逻辑分析
② 不同负载情况下性能表现差异
😈 请求流量构造
① 不同请求参数覆盖逻辑不同
② 线上真实流量情况
😈 压测范围
① 单机器压测
② 集群压测
😈 性能数据采集
① 单机性能数据
② 集群性能数据

🐷 分析性能数据,定位性能瓶颈

😈 使用库不规范
😈 高并发场景优化不足

🐷 重点优化项改造

😈 正确性是基础
😈 响应数据 diff
① 线上请求数据录制回放
② 新旧逻辑接口数据 diff

🐷 优化效果验证

😈 重复压测验证
😈 上线评估效果优化
① 关注服务监控、
② 逐步放量
③ 收集性能数据

🐷 进一步优化

😈 规范上游
😈 分析链路,通过业务流程优化提升服务性能

2. 基础库优化

🐷 分析基础库核心逻辑和性能瓶颈

😈 设计完善改造方案
😈 数据按需获取
😈 数据序列化协议优化

🐷 内部压测验证

🐷 推广业务服务落地验证

3. Go 语言优化

🐷 编译器 & 运行时优化

😈 优化内存分配策略
😈 优化代码编译流程,生成更高效的程序
😈 内部压测验证
😈 推广业务服务落地验证

🐷 优点

😈 接入简单,只需要调整编译配置
😈 通用性强

总结

🐷性能调优原则:要依靠数据不是猜测

🐷 性能分析工具 pprof:熟练使用 pprof 工具排查性能问题并了解其基本原理

🐷 性能调优

😈 保证正确性
😈 定位主要瓶颈