这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
一、本堂课重点内容:
- 如何写出高质量的代码(高质量编程)
- 性能优化
- 性能优化工具以及实战
二、详细知识点介绍:
-
高质量编程(正确可靠、简洁清晰)
- 各种边界条件是否考虑完善
- 异常情况处理,稳定性保证
- 易读易维护
- 代码格式(使用 gofmt 自动格式化代码)
- 注释
- 解释代码作用(适合解释公共符号)
- 解释代码如何做的(适合注释实现过程)
- 解释代码实现原因(适合解释代码外部因素、提供额外的上下文)
- 解释代码出错情况(解释代码限制条件)
- 命名规范
- 简洁胜于冗长
- 变量距离越远,需要越多的上下文信息
- 缩略词的大小写注意
- 函数名尽量短
- 函数名不包含包名
- 包名只用小写字母组成 不使用大写字母以及下划线
- 包名不与标准库同名
- 尽量使用单数不使用复数
- 控制流程
- 避免复杂嵌套
- 保持正常路径为最小路径(优先处理错误情况/特殊情况)
- 错误和异常处理
- 简单错误优先使用errors.New 来创建一个错误
- 错误的 Wrap 和 UnWrap 错误嵌套 在fmt.Errorf 中使用 %w 关联一个 err
- 判定是否错误 errors.Is 判断错误类型是否为指定类型 errors.As
- 不建议在业务代码中使用panic 可以在启动阶段使用panic
- recover 只能在defer中使用 嵌套无法生效 只在当前goroutine中生效
- 可以在recover后在log中记录当前调用栈
-
性能优化
- go自带性能测试工具 go test -bench=. -benchmem
- 在初始化slice时尽量提供容量信息
- 在已有的基础上创建创建切片,不会创建新的底层数组 可以用copy来代替直接使用原始切片
- map也可以预分配内存
- 字符串的拼接尽量使用 strings.Builder 来拼接
- 如果使用+号的话 会出现内存分配的时间,消耗的时间比较大
- map中使用空结构体来节省内存
- 空结构体不占用内存
- 可以用作各种情况下的占位符使用
- 可以使用map空结构体来实现set
- 使用atomic这个包来进行原子操作
- 对于非数值的操作 可以使用atomic.value 能够传入一个interface{}
-
性能优化工具 pprof
-
用于可视化和性能分析数据的工具
-
topN 查看占用资源最多的函数
-
list 使用指定的正则表达式查找代码行
-
web 调用关系可视化图
-
goroutine协程 使用火焰图来分析 每一个小块代表一个函数
-
cpu采样过程和原理
- 进程向操作系统注册一个定时器 每隔10ms 操作系统向进程发送SIGPROF信号
- 进程接收到SIGPROF信号就会记录堆栈信息
- 每隔100 ms会将信息写入到缓冲区
-
内存采样
- 记录内存分配器分配的内存/释放的大小
- 每隔512KB记录一次
-
协程/线程创建
- stop world -> range allg 切片 -> 输入g的堆栈 -> start world
-
阻塞/锁
- 采样阻塞/锁的耗时和次数
- 阻塞超过阈值才会记录
-
-
性能调优案例
-
业务服务优化
- 建立性能评估手段
- 分析性能数据,定位性能瓶颈
- 重点优化项改造
- 效果验证
-
基础库优化
- 分析基础库核心逻辑和性能瓶颈
- 内部压测验证
- 推广业务服务落地验证
-
go语言优化
- 编译器&运行时优化
- 优化代码编译流程
- 优化内存分配策略
-
三、实践练习例子:
本节课主要是理论知识与体会工具使用 实践练习例子比较少
四、课后个人总结:
- 通过本节课的学习,首先是学习了高质量代码的编程的要求
- 体会了性能优化的的原则与性能优化的工具
- 学习了性能调优的流程
- 性能优化主要是定位代码的主要瓶颈 在优化的时候要保证代码的正确性