分析性能分析工具 pprof| 青训营

100 阅读4分钟

性能分析工具 pprof: 性能调优的前提是对应用程序性能表现有实际的数据指标,对于Go程序,有一个很方便的工具就是pprof!

image.png

这里有一个开源项目,已经制造了一些问题代码,需要进行排查

wolfogre/go-pprof-practice: go pprof practice. (github.com)

实际分析排查过程 排查 CPU 问题

命令行分析 go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"

top 命令 list 命令

熟悉 web 页面分析

调用关系图,火焰图

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/cpu"

排查堆内存问题

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"

排查协程问题

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"

排查锁问题

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"

排查阻塞问题

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"

 pprof 的采样过程和原理

CPU 采样

堆内存采样

协程和系统线程采样

阻塞操作和锁竞争采样

CPU采样

CPU采样会记录所有调用栈和他们所占用的时间

在采样时,进程会每秒暂停一百次,每次记录当前的调度信息。汇总后,根据调用栈在采样中出现的次数来推断函数的运行时间

image.png

堆内存采样

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

采样率:每分配512KB记录一次

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

采样指标:alloc_space,alloc_objects,inuse_spac,inuse_objects

计算方式:inuse = alloc - free

协程和系统线程采样

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

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

  image.png

阻塞操作和锁竞争采样

  image.png

业务优化

流程:

建立服务性能评估手段

image.png

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

重点优化项改造

优化效果验证

建立服务性能评估手段   之所以不用benchmark是因为时间服务逻辑比较复杂,希望从更高的层面分析服务的性能问题,同时机器在不同负载下的性能也会不同

评估手段建立后,产出一个服务的性能指标分析报告

有了服务优化前的性能报告和一些性能采样数据,我们可以进行性能瓶颈分析

业务服务常见的性能问题可能是使用的基础组件不规范

类似日志使用不归发,一部分是调试日志发布到线上,一部分是线上服务在不同的调用链路上数据有差别,测试场景日志还好,但是到了真实线上全景场景,会导致日志数量增加影响性能

另外常见的性能问题就是高并发场景的优化不足

重点优化项改造:

正确性实际基础!

性能优化的前提是保证正确性,使用在变动较大的性能优化上线之前,需要进行正确性验证,借助自动化手段保证优化后程序的正确性

优化效果验证:

用同样的数据对优化后的服务进行压测,同时压测并不能保证和线上表现完全一致,有时还要通过线上的表现在进行分析改进,是个长期的过程

基础库优化

适应范围更广,覆盖更多服务

AB 实验 SDK 的优化:

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

完善改造方案,按需获取,序列化协议优化

内部压测验证

推广业务服务落地验证

Go语言优化

适应范围最广,Go 服务都有收益 

优化方式 

优化内存分配策略

优化代码编译流程,生成更高效的程序

内部压测验证

推广业务服务落地验证

总结

性能评估要依靠数据,用实际的结果做决策

对于pprof工具,可以通过分析实际的程序,熟悉相关功能,理解好基本原理,后续能够更好的解决性能问题

在真正的服务性能调优流程中,链路会很长,重点是要保证正确性,不影响功能,同时定位好问题