Go性能调优 2024-08-01 默认分类 暂无评论 219 次阅读 # **优化的方向** CPU占用 内存泄露 GC 频繁触发 协程泄露 锁竞争 阻塞 **衡量指标** CPU、内存、带宽、磁盘、异常率、响应时间(RT)、吞吐量 - 从多个方面着手分析 找到性能短板 - 优化要从整体考虑,尽量在优化一个方面时,不影响其他方面,或是其他方面略微下降。 - 优化的时候要考虑投入产出比 如果本身性能已经没多大优化空间应该从其他地方入手 **Go编码习惯** - 使用strconv 替代fmt.Sprint的数字到类型的转换 - map和slice 在初始化的时候指定合理的容量 减少内存分配的额度 避免频繁扩容 - []struct{} 使用下标而不是 range - 利用unsafe包避开内存copy (高级技巧慎用) - 使用sync.Pool 复用对象 (降低垃圾回收压力) - 避免系统调用 **设计上的优化** - 并行处理 相互无关的任务 同时处理 提升资源利用率 - 池化技术: (对象复用 协程池化) - 异步处理: 将无需等待结果的任务 放到后台异步进行 - 优化算法: 使用合理的数据结构和计算方法 - 空间换时间 (数据库索引,数据缓存) - 或者时间换空间 (压缩算法, 虚拟内存, 垃圾回收) - 善于使用设计模式: 对代码结构进行优化 - 选择性能更好的第三方库 **代码层面** - 垃圾回收 - 内存泄漏问题 - 连接池优化持久链接 - Ballast Object - CPUWorker CFS算法? - TiExec **容器层面** - 使用最小化的基础镜像 Alpine发行版 - 设置resouce限制 资源 - HPA(Horizontal Pod Autoscaler) - 利用健康检查和 readiness 探针 **工具篇** - benchmark - go test -bench . -benchtime=5s -count=3 - go test -bench . -benchmem - pprof - trace 工具篇 pprof **启用pprof** ``` Go import _ "net/http/pprof" go func() { http.ListenAndServe("localhost:5000", http.DefaultServeMux) }() ``` 同时将程序run起来后, 我们通过访问 `http://127.0.0.1:6060/debug/pprof/` 就可以看到如下页面: ![image.png](http://res.i-cooltea.top/image/20240819113209.png) 点击profile就可以下载cpu profile文件。那我们如何查看我们的性能报告呢? pprof支持两种查看模式,终端和web界面,**注意: 想要查看可视化界面需要提前安装graphviz。** **通过以下命令即可启动web界面** 这里我们以web界面为例,在终端内我们输入如下命令: ``` shell go tool pprof -http :6060 test_cpu go tool pprof -http=:3001 http://localhost:16060/debug/pprof/allocs ``` 就会在浏览器里打开一个页面,内容如下: 从界面左上方VIEW栏下,我们可以看到,pprof支持Flame Graph,dot Graph和Top等多种视图,下面我们将一一介绍如何阅读这些视图。 火焰图 首先,**推荐直接阅读火焰图**,在查函数耗时场景,这个比较直观; 最简单的:**横条越长,资源消耗、占用越多;** 注意:每一个function 的横条虽然很长,但可能是他的下层“子调用”耗时产生的,所以一定要关注“下一层子调用”各自的耗时分布; 每个横条支持点击下钻能力,可以更详细的分析子层的耗时占比。 ![image.png](http://res.i-cooltea.top/image/20240819113621.png) dot Graph 英文原文在这里:https://github.com/google/pprof/blob/master/doc/README.md ![image.png](http://res.i-cooltea.top/image/20240819113638.png) - 节点颜色: - 红色表示耗时多的节点; - 绿色表示耗时少的节点; - 灰色表示耗时几乎可以忽略不计(接近零); - **节点字体大小 :** - 字体越大,表示占“上层函数调用”比例越大;(其实上层函数自身也有耗时,没包含在此) - 字体越小,表示占“上层函数调用”比例越小; - **线条(边)粗细:** - 线条越粗,表示消耗了更多的资源; - 反之,则越少; - **线条(边)颜色:** - 颜色越红,表示性能消耗占比越高; - 颜色越绿,表示性能消耗占比越低; - 灰色,表示性能消耗几乎可以忽略不计; - **虚线** :表示中间有一些节点被“移除”或者忽略了;(一般是因为耗时较少所以忽略了) - **实线** :表示节点之间直接调用 - 内联边标记:被调用函数已经被内联到调用函数中 (对于一些代码行比较少的函数,编译器倾向于将它们在编译期展开从而消除函数调用,这种行为就是内联。) top 在pprof中执行 top命令查询结果 字段含义解析 - flat:当前函数,运行耗时(不包含内部调用其他函数的耗时) - flat%:当前函数,占用的 CPU 运行耗时总比例(不包含外部调用函数) - sum%:当前行的 flat% 与上面所有行的 flat% 总和。 - cum:当前函数加上它内部的调用的运行总耗时(包含内部调用其他函数的耗时) - cum%:同上的 CPU 运行耗时总比例 trace ``` Shell // 代码中加入 trace.Start(os.Stderr) defer trace.Stop() // 启动时 将trace结果输出到trace_xxx.out中 ./app > trace_xxx.out // 使用trace工具进行分析 go tool trace trace_xxx.out ``` pprof已经有了对内存和CPU的分析能力,那trace工具有什么不同呢?虽然pprof的CPU分析器, 可以告诉你什么函数占用了最多的CPU时间,但它并不能帮助你定位到是什么阻止了goroutine运行, 或者在可用的OS线程上如何调度goroutines。这正是trace真正起作用的地方。 我们需要更多关于Go应用中各个goroutine的执行情况的更为详细的信息, 可以从P(goroutine调度器概念中的processor)和G(goroutine调度器概念中的goroutine) 的视角完整的看到每个P和每个G在Tracer开启期间的全部“所作所为”, 对Tracer输出数据中的每个P和G的行为分析并结合详细的event数据来辅助问题诊断的。 Tracer可以帮助我们记录的详细事件包含有: - 与goroutine调度有关的事件信息:goroutine的创建、启动和结束;goroutine在同步原语(包括mutex、channel收发操作)上的阻塞与解锁。 - 与网络有关的事件:goroutine在网络I/O上的阻塞和解锁; - 与系统调用有关的事件:goroutine进入系统调用与从系统调用返回; - 与垃圾回收器有关的事件:GC的开始/停止,并发标记、清扫的开始/停止。 Tracer主要也是用于辅助诊断这三个场景下的具体问题的: - 并行执行程度不足的问题:比如没有充分利用多核资源等; - 因GC导致的延迟较大的问题; - Goroutine执行情况分析,尝试发现goroutine因各种阻塞 (锁竞争、系统调用、调度、辅助GC)而导致的有效运行时间较短或延迟的问题。 参考 [第 126 期 2022-01-18 Go 自底向上性能优化实践](https://talkgo.org/t/topic/3296) [轻风博客 - 高德Go生态的服务稳定性建设|性能优化的实战总结 ](https://www.cnblogs.com/88223100/p/Service-Stability-Construction-of-Gaode-Go-Ecology-Practical-Summary-of-Performance-Optimization.html) [6.3 Go 大杀器之跟踪剖析 trace](https://golang2.eddycjy.com/posts/ch6/03-trace/) [Garbage Collection In Go : Part I - Semantics](https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html) [Garbage Collection In Go : Part II - GC Traces](https://www.ardanlabs.com/blog/2019/05/garbage-collection-in-go-part2-gctraces.html) [Garbage Collection In Go : Part III - GC Pacing](https://www.ardanlabs.com/blog/2019/07/garbage-collection-in-go-part3-gcpacing.html) 文章目录 工具篇 pprof 火焰图 dot Graph top trace 参考 标签: golang 转载请注明文章来源 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭