5.11 高质量编程与性能调优实战 | 青训营笔记

222 阅读6分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记

1.高质量编程

1.1简介

  1. 高质量代码
    1. 正确可靠
    2. 简介清晰
  2. 编程原则(来自开发者Dave Cheney)
    1. 简单性
    2. 可读性
    3. 生产力

1.2编程规范

代码格式

  1. gofmt
    1. 格式化代码
  2. goimports
    1. 格式化代码
    2. 自动增删依赖包

注释

  • 注释应该做的
    • 解释代码作用
      • 适合注释公共符号
      • 但是,如果一些直接通过函数名已经知道功能的函数,就没必要写注释了
    • 解释代码是如何做的
      • 适合注释实现过程
    • 解释代码实现的原因
      • 适合解释代码的外部因素
      • 提供额外上下文
    • 解释代码什么情况会出错
      • 适合解释代码的限制条件
  • 公共符号应该注释

看一个很好的注释示例 image.png

小结
  1. 代码是最好的注释(因为可能出现代码跟注释不一致的情况,所以要以代码为主)
  2. 注释应该提供代码为表达出来的上下文信息

命名规范

  1. variable

image.png 例子image.png

  1. function

image.png

  1. package

image.png

小结
  1. 降低阅读理解代码的成本
  2. 重点考虑上下文信息,设计简洁清晰的名称

阅读代码多了之后就会知道什么样的名称会更好

控制流程

  1. 避免嵌套,保持正常流程清晰
    1. 比如if else例子
  2. 尽量保持正常代码路径为最小缩进

image.png 调整后image.png

错误和异常处理

  1. 简单错误

image.png

  1. 对于复杂的错误:错误的Wrap和Unwrap

image.png

  1. 错误判定

image.png image.png As跟Is的区别在于,可以将类型错误的特定内容取出来

  1. panic

image.png

  1. recover
  • 将出现panic的上下文记录下来,常见的就是将panic的调用栈打印出来

image.png

小结

image.png

1.3.性能优化建议

1.3.1Benchmark

如何使用

命令 image.png

结果

了解每个值代表的含义是什么 image.png

1.3.2 Slice

预分配内存

  • 尽可能使用make()初始化切片时提供容量信息,第三个参数

另一个大陷阱:大内存未释放

推荐做法:使用copy函数,不要直接在数组上面进行操作

1.3.3Map

预分配内存

  • 初始化一下map的大小

image.png image.png

1.3.4字符串处理

使用strings.Builder

image.png

1.3.5空结构体

使用空结构体节省内存

image.png

1.3.6atomic包

如何使用atomic包

用这个atomic包比加锁的性能要高很多 image.pngimage.png

小结

image.png

2.性能调优实战

2.1简介

性能调优原则

image.png

2.2性能分析工具pprof

说明

  1. 可以知道应用在什么地方消耗了多少CPU、Memory
  2. 是用于可视化和分析性能分析数据的工具

2.2.1pprof功能简介

四个功能模块,展示方法也有很多种 image.png

2.2.2排查实战

搭建pprof实践项目

image.png

浏览器查看指标

先将项目运行起来,然后在搜索框输入:localhost:6060/debug/pprof image.png

从CPU排查开始

在终端输入下图所示的命令,查看cpu的使用情况,命令中限制了搜集的时间是10s pprof必须要拿到文件才能进行性能的分析,敲完命令之后稍等一会,出现跟下面图片的结果一样的时候就是成功了 image.png 接下来看看怎么进行性能的分析: 进入pprof的话,输入**top命令**,就会出现以下结果,关注一下每一列的含义 image.png 分析一下以下两种情况Flat跟Cum image.png 结果如下 image.png

list命令

  • 可以定位到指定的代码行

image.png

web命令

  • 调用关系可视化

image.png

Heap-堆内存

  • 查看以下堆堆堆内存的一些情况

在终端输入命令:go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap",然后就会跳转到一个页面里面

出现问题

出现以下提示 Could not execute dot; may need to install graphviz. 搜索怎么安装graphviz:参考这个帖子

wsl中的ubuntu的解决方法

在wsl中换到ubuntu的,进行安装,但是需要root用户才能对他进行安装,参考这篇博客 此时上面步骤走完后出现这种情况: image.png 解决方法: image.png

windows里面的解决方法

参考链接:stackoverflow.com/questions/2… image.png

  • 成功打开后的结果如下图所示

image.png

  • 也可以在VIEW菜单那里切换不同类型的图
  • SAMPLE目录,四个字段的意思

image.png

goroutine-协程

  • goroutine泄露也会导致内存泄漏

使用命令来进行查看:go tool pprof -http:8080 "http://localhost:6060/debug/pprof/goroutine"

详细介绍一下火焰图

  • 可以点击某一个块进入代码

image.png

mutex-锁

在terminal输入命令:go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"

  • 先看一下grap视图,看看可能有问题的方法,然后到source里面找到对应的代码,注释掉它

block-阻塞

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

  • 思路跟上面的一样

image.png

小结

标星的就是需要重点关注的点 image.png

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

CPU

image.png 详细流程: image.png

Heap-堆内存

image.png

Goroutin-协程&ThreadCreate-线程创建

这两个比较相似 image.png

Block-阻塞&Mutex-锁

image.png

小结

image.png

2.3性能调优案例

简介

  • 介绍实际业务性能调优的案例
  • 堆逻辑相对复杂的程序如何进行性能调优

优化可以分为以下3类

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

2.3.1业务服务优化

基本概念

系统部署的示意图,最上面一层是用户端的,下面都是服务端的内容,到网关这一层之后,就会把数据转发到具体的业务服务上面,SeviceA调用ServiceB,就可以叫做,ServiceA依赖于ServiceB image.png

流程

分4步 image.png

1.建立服务性能评估手段

image.png 同过压测平台,对服务会产生一个压测报告,看一下压测报告实际关注了哪些指标

  1. 接口耗时
  2. QPS

曲线就是实际压测的曲线 image.png

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

有了数据结果之后,看一下实际的内容,火焰图定位一下火焰图很长的块

  • 使用库不规范

image.png

  • 高并发场景优化不足

对比一下,高峰期的时候跟低风期的时候,性能变化比较大的块 image.png

3.重点优化项改造

image.png

4.优化效果验证