Go第三课 | 青训营笔记

48 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第3天,今天学习了高质量编程简介及编码规范、性能优化分析工具这部分的内容。对go的编码规范和原则有了一些了解,特别是学习了控制流程和异常处理部分的最佳实践;另外对常见容器的底层实现和优化思路有了认知;然后通过项目实践学习了如何使用pprof工具分析程序cpu、内存、goroutine的性能瓶颈的方法。

封面来自于github.com/rfyiamcool/…

课程一

高质量编程

高质量定义:代码正确可靠、简洁清晰

原则

  1. 简单性:清晰简单,复杂功能要解耦
  2. 可读性
  3. 生产力:团队工作效率

规范

  1. gofmt自动格式化
  2. 注释:作用(功能)+过程+实现原因+报错(怎么处理不合法输入)
    写代码未表达的上下文信息
  3. 命名:
    变量名:缩略词全大写,但需要导出的全小写
    函数名:不要携带包名上下文
    包命名:不要和标准库重复
  4. 控制流程:

if需要减少else
image.png

优先处理异常
image.png

  1. 错误和异常处理:

简单错误:erros.New
错误跟踪链条:%w image.png

err.Is:取出特定错误

image.png

err.As:获取特定错误

image.png

panic:启动逻辑可以用panic,其他时候少用
recover:只能在defer函数用,只在当前goroutine生效,debug.Stack()打印
defer:后进先出

课程二

性能评估指标:Benchmark工具

结果说明

image.png

slice && map

  1. 尽可能初始化时指定大小
  2. 在已有切片上创建切片,不会创建新的底层数组,原切片较大的场景可以copy

切片本质是一个数组片段的描述

string

strings.Builder 比较好 字符串属于不可变类型,其内存大小固定,使用+会导致重新分配内存

image.png

可预分配,strings.builder 和 bytes.Buffer都可以用Grow预分配内存

空结构体

空结构体不占内存,可用于实现set如 map[int]struct{}

atomic

  1. 在单一变量的增减操作上替代加锁
  2. 锁是OS实现,atomic是硬件实现效率高
  3. Mutex可用来保护逻辑不仅限于值,atomic.Value可承载interface{}

课程三

性能优化:靠数据而不是靠猜,不要过早优化

pprof

浏览器打开http://127.0.0.1:6060/debug/pprof/

image.png flat == 0函数只有其他函数的调用
flat == cum 函数没有调用其他函数

cpu占用高

go tool pprof "http://127.0.0.1:6060/debug/pprof/profile?seconds=10"

image.png

内存占用多

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

我Ubuntu虚拟机没有安装graphviz有报错,参考graphviz.org/download/安装

image.png

VIEW-Source查看,点具体语句可以看汇编,这里growslice消耗多应该是分配内存的问题

image.png

协程多

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

image.png

火焰图:从上到下表示调用顺序,长度代表占CPU时间长

PS:注意,存在一些过滤规则,因此不是所有的数据都会展示分析出来

课程四

pprof采样原理

cpu

注册定时器

堆内存

内存分配器在对上,512KB记录一次

协程

遍历列表,输出堆栈

阻塞&&锁

  1. 阻塞 超过阈值才记录
  2. 锁 记录比例

案例

  1. 保持正确性
  2. 定位主要的瓶颈

业务服务

覆盖流量请求,压测

总结

有收获的一天