Go 语言高质量编程与性能调优实战篇 | 青训营笔记

119 阅读5分钟

这是我参与「第五届青训营」笔记创作活动的第3天。笔记旨在记录自己的学习过程以及跟更多人分享交流,重点讲干货,不扣细节,从整体认知。废话不多说,上内容!!!

本堂课重点内容

  • 介绍编码规范,帮助大家写出高质量程序
  • 介绍 Go 语言的性能优化建议,分析对比不同方式对性能的影响和背后的原理
  • 讲解常用性能分析工具 pprof 的使用和工作原理,熟悉排查程序性能问题的基本流程
  • 分析性能调优实际案例,介绍实际性能调优时的工作内容

详细知识点介绍

高质量编程

  1. 简介 -> 编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码

正确性 : 是否考虑各种边界条件,错误的调用是否能够处理

可靠性 : 异常情况或者错误的处理策略是否明确,依赖的服务出现异常是否能够处理

简洁 : 逻辑是否简单,后续调整功能或新增功能是否能够快速支持

清晰 : 其他人在阅读理解代码的时候是否能清楚明白,重构或者修改功能是否不会担心出现无法预料的问题

关于 Go 语言开发者 Dave Cheney 的一些原则

①简单性

消除"多余的复杂性”,以简单清晰的逻辑编写代码

不理解的代码无法修复改进

②可读性

代码是写给人看的,而不是机器

编写可维护代码的第一步是确保代码可读

③生产力

团队整体工作效率非常重要

  1. 编码规范

代码格式 -> 推荐使用gofmt自动格式化代码

注释 -> 注释应该解释代码作用

注释应该解释代码如何做的

注释应该解释代码实现的原因

注释应该解释代码什么情况会出错

注释应该提供代码未表达出的上下文信息

命名规范 ->

简洁胜于冗长

缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写

例如使用ServeHTTP而不是ServeHttp

使用XMLHTTPRequest 或者xmlHTTPRequest

变量距离其被使用的地方越远,则需要携带越多的上下文信息

全局变量在其名字中需要更多的上下文信息,使得在不同地方可以轻易辨认出其含义

控制流程 -> 避免嵌套,保持正常流程清晰

尽量保持正常代码路径为最小缩进

线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支

正常流程代码沿着屏幕向下移动

提升代码可维护性和可读性

故障问题大多出现在复杂的条件语句和循环语句中

错误和异常处理 ->

error 尽可能提供简明的上下文信息链,方便定位问题

panic 用于真正异常的情况

recover 生效范围,在当前 goroutine 的被 defer 的函数中生效

  1. 性能优化的建议

性能优化的前提是满足正确可靠、简洁清晰等质量因素

性能优化是综合评估,有时候时间效率和空间效率可能对立

针对Go语言特性,介绍Go相关的性能优化建议

使用 Go 语言提供了支持基准性能测试的 benchmark 工具

1.png

针对 slice (预分配内存、大内存未释放)、map (预分配内存)、字符串的处理 (strings.Builder)、空结构体 (节省内存)、atomic 包

2.png

3.png

性能调优实战

  1. 性能调优原则

要依靠数据不是猜测

要定位最大瓶颈而不是细枝末节

不要过早优化

不要过度优化

  1. 性能分析工具

希望知道应用在什么地方耗费了多少CPU、Memory

pprof是用于可视化和分析性能分析数据的工具

pprof 功能简介

1.png

pprof 排查实战

2.png

在浏览器中打开 http://localhost:6060/debug/pprof,

1.CPU
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"

链接结尾的 profile 代表采样的对象是 CPU 使用。如果你在浏览器里直接打开这个链接,会启动一个60秒的采样,并在结束后下载文件。这里我们加上 seconds = 10 的参数,让它采样十秒。

list

根据指定的正则表达式查找代码行

web

调用关系可视化

3.png

4.png

2.Heap

alloc_objects:程序累计申请的对象数

inuse_objects:程序当前持有的对象数

alloc_space:程序累计申请的内存大小

inuse_space:程序当前占用的内存大小

3.goroutine-协程

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

goroutine 泄露也会导致内存泄露

由上到下表示调用顺序

每一块代表一个函数,越长代表占用CPU的时间更长

火焰图是动态的,支持点击块进行分析

支持搜索,在 Source 视图下搜索 wolf

注释问题代码后的结果

4.mutex-锁

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

5.block-阻塞

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

pprof的采样过程和原理

5.png

6.png

7.png

8.png

9.png

实践练习例子

性能调优案例

业务服务优化

10.png

流程 :

建立服务性能评估手段

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

重点优化项改造

优化效果验证

11.png

12.png

13.png

14.png

15.png

16.png

17.png

基础库优化

18.png

Go 语言优化

19.png

课后个人总结

  1. 高质量编程让我学会了怎么写代码更加的全面,细致,高效;
  2. 性能调优中我学到了更多, pprof工具的使用,以及实战部分;

关于文中代码项目下载

  1. 安装 Git,参考 链接
  2. 登录 Github clone 性能分析工具 pprof-排查实战
  3. 从 Github 上克隆项目,参考 链接

引用参考

  1. 稀土掘金字节内部课
  2. 高质量编程与性能调优实战
  3. 后端专场 学习资料一 第五届字节跳动青训营