性能优化
总结:不需要像学习中那样对算法细枝末节进行优化,而是着重常见的性能陷阱即可
Benchmark
Slice、map、strings.Builder 预分配内存
另一个陷:大内存未释放
在已有切片基础上创建切片,不会创建新的底层数组场景
原切片较大,代码在原切片基础上新建小切片原底层数组在内存中有引用,得不到释放
可使用copy替代re-slice
字符串处理:
使用strings.Builder 使用+拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Buffer更快 分析: 字符串在Go语言中是不可变类型,占用内存大小是固定的 使用+每次都会重新分配内存 strings.Builder,bytes.Buffer底层都是byte数组 内存扩容策略,不需要每次拼接重新分配内存
使用空结构体节省内存:如用map实现set,此时只需要用到map的键
避免常见性能陷阱即可保证大部分程序性能
性能调优实践
性能调优
性能调优原则: 要依靠数据不是猜测 要定位最大瓶颈而不是细枝木节不要过早优化 不要过度优化
pprof实战
功能简介:
使用命令
go tool pprof 'http://localhost:6060/debug/pprof/profile?seconds=10"
CPU 命令:topN 查看占用资源最多的函数
flat --当前函数本身的执行耗时 flat% --flat占CPU总时间的比例 sum% -- 上面每一行的flat%总和 cum --指当前函数本身加上其调用函数的总耗时 cum% --cum占CPU总时间的比例
Flat=Cum,函数中没有调用其他函数 Flat=0,函数中只有其他函数的调用
命令web
调用关系可视化
个人总结:可视化更加容易观察,如火焰图
Heap-堆内存
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/heap 可视化展示内存问题
goroutine-协程
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/goroutine
source视图下可搜索相应代码
mutex-锁
后缀改成mutex即可
个人理解:整个过程就是利用性能分析工具,逐个分析哪些方面占用性能较大并解决
调优案例
个人思考:调优其实不论是业务还是库还是语言调优,基本逻辑都相同,即使用分析工具,在高峰、低峰时段对性能分别检测,分析清楚业务原理,优化占用性能的相应业务, 基本概念
服务:能单独部署,承载一定功能的程序依赖:SenviceA的功能实现依赖 ServiceB的响应结果,称为ServiceA依赖ServiceB 调用链路:能支持一个接口请求的相关服务集合及其相互之间的依赖关系 基础库:公共的工具包、中间件
重复调用、异步处理等都可通过火焰图来看
性能调优原则
要依靠数据不是猜测
性能分析工具pprof 熟练使用pprof 工具排查性能问题并了解其基本原理性能调优 保证正确性 定位主要瓶颈
个人思考:性能调优不同于我们参加的算法竞赛,与其对细枝末节十分在意,更主要的是保证业务大体上的稳定。