入门 Go 语言-高质量编程与性能调优(三)| 青训营笔

64 阅读4分钟

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

入门 Go 语言-高质量编程与性能调优(三)

性能调优实战

性能分析工具 pprof-采样过程和原理

CPU

  • 采样对象:函数调用和它们占用的时间
  • 采样率:100次/秒,固定值
  • 采样时间:从手动启动到手动结束
graph LR
开始采样 --> 设定信号处理函数--> 开定时器
停止采样 --> 取消信号处理函数--> 取消时器

CPU

  • 操作系统
    • 每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的调用栈信息
    graph LR
    StopTheWorld --> 遍历allg切片 --> 输出创建g的堆栈 --> StartTheWorld
    
  • ThreadCreate
    • 记录程序创建的所有系统线程的信息
      graph LR
      StopTheWorld --> 遍历allm链表 --> 输出创建m的堆栈 --> StartTheWorld
      

Block-阻塞& Mutex-锁

  • 阻塞操作
    • 采样阻塞操作的次数和耗时
    • 采样率:阻塞耗时超过阈值的才会被记录,
    • 1为每次阻塞均记录
graph TD
阻塞操作 --上报调用栈和消耗时间--> Profiler -->时间未到阈值则丢弃
Profiler --采样--> 遍历阻塞记录 --> 统计阻塞次数和耗时
  • 锁竞争
    • 采样争抢锁的次数和耗时
    • 采样率:只记录固定比例的锁操作,1为每次加锁均记录
graph TD
竞争操作 --上报调用栈和消耗时间--> Profiler -->比例未命中则丢弃
Profiler --采样--> 遍历锁记录 --> 统计锁竞争次数和耗时

小结

  • 掌握常用pprof工具功能
  • 灵活运用pprof工具分析解决性能问题
  • 了解pprof的采样过程和工作原理

性能调优案例

简介

  • 业务服务优化
  • 基础库优化
  • Go语言优化

性能调优案例-业务服务优化

基本概念

  • 服务:能单独部署,承载一定功能的程序
  • 依赖:Service A 的功能实现依赖Service B的响应结果,称为Service A依赖Service B
  • 调用链路:能支持一个接口请求的相关服务集合及其相互之间的依赖关系
  • 基础库:公共的工具包、中间件

流程

  • 建立服务性能评估手段
  • 分析性能数据,定位性能瓶颈·重点优化项改造
  • 优化效果验证

建立服务性能评估手段·服务性能评估方式

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

建立服务性能评估手段 分析性能数据,定位性能瓶颈

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

重点优化项改造

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

优化效果验证

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

进一步优化,服务整体链路分析

  • 规范上游服务调用接口,明确场景需求
  • 分析链路,通过业务流程优化提升服务性能

AB实验SDK的优化

  • 分析基础库核心逻辑和性能瓶颈
    • 设计完善改造方案
    • 数据按需获取
    • 数据序列化协议优化
  • 内部压测验证
  • 推广业务服务落地验证

性能调优案例-Go语言优化

编译器&运行时优化

  • 优化内存分配策略
  • 优化代码编译流程,生成更高效的程序。内部压测验证
  • 推广业务服务落地验证
  • 优点
    • 接入简单,只需要调整编译配置
    • 通用性强

总结

  • 性能调优原则
    • 要依靠数据不是猜测
  • 性能分析工具 pprof
    • 熟练使用pprof工具排查性能问题并了解其基本原理
  • 性能调优
    • 保证正确性
    • 定位主要瓶颈