这是我参与「第五届青训营 」伴学笔记创作活动的第3天,今天学习了高质量编程简介及编码规范、性能优化分析工具这部分的内容。对go的编码规范和原则有了一些了解,特别是学习了控制流程和异常处理部分的最佳实践;另外对常见容器的底层实现和优化思路有了认知;然后通过项目实践学习了如何使用pprof工具分析程序cpu、内存、goroutine的性能瓶颈的方法。
课程一
高质量编程
高质量定义:代码正确可靠、简洁清晰
原则
- 简单性:清晰简单,复杂功能要解耦
- 可读性
- 生产力:团队工作效率
规范
- gofmt自动格式化
- 注释:作用(功能)+过程+实现原因+报错(怎么处理不合法输入)
写代码未表达的上下文信息 - 命名:
变量名:缩略词全大写,但需要导出的全小写
函数名:不要携带包名上下文
包命名:不要和标准库重复 - 控制流程:
if需要减少else
优先处理异常
- 错误和异常处理:
简单错误:erros.New
错误跟踪链条:%w
err.Is:取出特定错误
err.As:获取特定错误
panic:启动逻辑可以用panic,其他时候少用
recover:只能在defer函数用,只在当前goroutine生效,debug.Stack()打印
defer:后进先出
课程二
性能评估指标:Benchmark工具
结果说明
slice && map
- 尽可能初始化时指定大小
- 在已有切片上创建切片,不会创建新的底层数组,原切片较大的场景可以copy
切片本质是一个数组片段的描述
string
strings.Builder 比较好
字符串属于不可变类型,其内存大小固定,使用+会导致重新分配内存
可预分配,strings.builder 和 bytes.Buffer都可以用Grow预分配内存
空结构体
空结构体不占内存,可用于实现set如 map[int]struct{}
atomic
- 在单一变量的增减操作上替代加锁
- 锁是OS实现,atomic是硬件实现效率高
- Mutex可用来保护逻辑不仅限于值,atomic.Value可承载interface{}
课程三
性能优化:靠数据而不是靠猜,不要过早优化
pprof
浏览器打开http://127.0.0.1:6060/debug/pprof/
flat == 0函数只有其他函数的调用
flat == cum 函数没有调用其他函数
cpu占用高
go tool pprof "http://127.0.0.1:6060/debug/pprof/profile?seconds=10"
内存占用多
go tool pprof -http=:8080 "http://127.0.0.1:6060/debug/pprof/heap"
我Ubuntu虚拟机没有安装graphviz有报错,参考graphviz.org/download/安装
VIEW-Source查看,点具体语句可以看汇编,这里growslice消耗多应该是分配内存的问题
协程多
go tool pprof -http=:8080 "http://127.0.0.1:6060/debug/pprof//goroutine"
火焰图:从上到下表示调用顺序,长度代表占CPU时间长
PS:注意,存在一些过滤规则,因此不是所有的数据都会展示分析出来
课程四
pprof采样原理
cpu
注册定时器
堆内存
内存分配器在对上,512KB记录一次
协程
遍历列表,输出堆栈
阻塞&&锁
- 阻塞 超过阈值才记录
- 锁 记录比例
案例
- 保持正确性
- 定位主要的瓶颈
业务服务
覆盖流量请求,压测
总结
有收获的一天