这是我参与「第五届青训营 」笔记创作活动的第3天
重点内容
- 如何编写更简洁清晰的代码
- 常用Go语言程序优化手段
- 熟悉Go程序性能分析工具
- 了解工程中性能优化的原则和流程
知识点介绍
-
什么是高质量
- 各种边界条件是否完备
- 异常情况处理,稳定性保障
- 易读易维护
——编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码
-
编程原则
-
简单性
- 消除“多余的复杂性”,以简单清晰的逻辑写代码
- 不理解的代码无法修复改进
-
可读性
- 代码是写给人看的,而不是机器
- 编写可维护代码的第一步是确保代码可读
-
生产力
- 团队整体工作效率非常重要
-
-
如何编写高质量代码
-
代码格式
-
注释
- 包中声明的每个公共的符号:变量、常量、函数以及结构都需要添加注释
- 任何既不明显也不简短的公共功能必须予以注释
- 无论长度或复杂度如何,对库中的任何函数都必须进行注释
-
命名规范
- 简洁胜于冗长
- 缩略词全部大写,但当其位于变量开头不需要导出时,使用全小写
- 变量距离其被使用的地方越远,则需要携带越多的上下文信息
-
控制流程
-
// Bad if foo { return x } else { return nil } // Good if foo { return x } return nil
- 正常流程路径为最小缩进
-
-
错误和异常处理
- 不建议在业务代码中使用panic
- init main函数内中可以使用panic
-
-
Benchmark
Go语言提供了支持基准性能测试的benchmark工具
go test -bench=. -benchmem
-
性能优化建议
- slice、map预分配内存
- 在已有大切片上创建新切片,可以使用copy代替re-slice
- 使用strings.Builder处理字符串
- 使用空结构体节省内存(例子,使用map实现set)
- 使用atomic包,通过硬件实现,效率更高
- 普通应用代码不要一味追求性能
-
性能调优原则
- 依靠数据而不是猜测
- 要定位到最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
-
业务服务优化
-
服务性能评估方式
- 单独benchmark无法满足复杂逻辑分析
- 不同负载情况下性能表现差异
-
请求流量构建
- 不同请求参数覆盖逻辑不同
- 线上真实流量情况
-
压测范围
- 单机器压测
- 集群压测
-
性能数据采集
- 单机性能数据
- 集群性能数据
-
实践
pprof排查实战
常用命令
go tool pprof http://localhost:6060/debug/pprof/profile
go tool pprof http://localhost:6060/debug/pprof/heap
go tool pprof http://localhost:6060/debug/pprof/allocs
| 名称 | 含义 |
|---|---|
| flat | 当前函数本身的执行耗时 |
| flat% | flat占CPU总时间的比例 |
| sum% | 上面每一行的 flat% 总和 |
| cum | 当前函数本身加上其调用函数的总耗时 |
| cum% | cum占CPU总时间的比例 |
- Flat == Cum,函数没有调用其他函数
- Flat == 0, 函数只调用了其他函数