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

102 阅读3分钟

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

高质量

边界条件考虑完备、处理异常情况、易读易维护

代码格式

gofmt

或者goimports

注释

提供额外信息

命名规范

简洁

(包名)

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

(函数)

不携带包名的上下文信息,因为包名和函数名总是成对出现

尽量简短

(包package)

只由小写字母组成,不含大写字母、下划线

不要和标准库同名

控制流程

避免嵌套,保持正常流程清晰

保持正常代码路径为最小路径

线性原理

优先处理错误情况/特殊情况,尽早返回或继续循环来减少嵌套

成功的退出条件 return nil

最后一行返回一个错误,需要追溯到匹配的左括号,才能了解何时会触发错误

错误和异常处理

简单错误(只出现一次的错误,其他地方不需要捕获该错误)

errors.New创建匿名变量

获取特定类型的错误

errors.AS

recover

只能在被defer的函数中使用

defer语句

函数返回前调用

多个defer语句是后进先出

嵌套无法生效,只在目前goroutine生效

后进先出

panic不建议在业务代码中使用,而是用于真正异常的情况

性能优化

go自带的支持基准性能测试的 benchmark

go test -bench =. -benchmem

slice预分配内存

尽可能在使用 make() 初始化切片时,提供容量信息

(减少分配次数)

切片本质是对数组片段的描述

map预分配内存

增加元素导致扩容

提前分配空间,减少内存拷贝和rehash的消耗

strings.Builder

使用+拼接性能最差

字符串在go中占用内存大小固定

使用+每次都会重新分配内存

空结构体,不占内存,当占位符

struct()

使用 atonic包

实战

性能调优原则:依靠数据而不是猜测、定位最大瓶颈而不是细枝末节

性能分析工具pprof

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

web命令,调用关系可视化

heap 堆内存

执行命令 go tool pprof -http=:8080

"http://localhost:6060/debug/pprof/heap"

火焰图

从上到下表示调用顺序

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

业务服务优化

image.png

系统部署的简单示意图,客户端请求经过网关转发,由不同的业务服务处理,可能依赖其他服务,或存储、消息队列等组件

service B 被A 依赖,同时也依赖存储和 D

核心:发现服务性能的瓶颈

json解析:数据变更时再重新解析json, 可以减少cpu资源占用

高并发场景下的性能:火焰图对比

监控组件的数据上报说同步请求,造成阻塞

改成异布上报的机制提升性能

在熟悉服务的整体部署情况后,可以针对更具体的接口链路进行 调优,例如是否存在重复调用、是否更小的结果数据集就能满足需求、接口是否需要实时数据、是否能在调用方进行缓存,减轻调用压力