这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。
高性能编程与调优实战
高质量编程
含义:编写的代码能够达到正确可靠、简洁清晰的目标
- 各种边界条件是否考虑完备
- 异常情况处理、稳定性保证
- 易读易维护
编程原则
- 简单性:消除“多余的复杂性”
- 可读性: 编写可维护代码的第一步是确保代码可读
- 生产力
编码规范
- 代码格式
- 使用gofmt自动格式化代码,自动格式化go语言代码为官方统一风格
- 注释:(注释应该提供代码未表达出的上下文信息)
- 注释应该解释代码的作用
- 注释应该解释代码是如何做的
- 注释应该解释代码实现的原因
- 注释应该解释代码什么情况下会出错
- 公共符号始终需要注释,例外:不需要注释实现接口的方法
- 命名规范
- 简洁胜过冗长
- 缩略词全大写,但当其位于变量开头而且不需要导出时,使用全小写
- 例如:ServeHTTP instead of ServeHttp
- XMLHTTPRequest or xmlHTTPRequest
- 变量距离其被使用的地方越远,则需要携带越多的上下文信息
- 对于函数:函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的
- "好的命名就像一个好笑话,如果你必须解释它,那就不好笑了"
- 控制流程
- 避免嵌套,保持正常流程清晰
- 优先处理错误情况/特殊情况,尽早返回或继续循环来减少嵌套
- 错误和异常处理
性能优化建议
- 性能优化是综合评估,有时候时间效率和空间效率可能对立
- 针对Go特性
使用Benchmark,测试性能
性能优化:slice
- slice应尽可能在使用make()初始化切片时提供容量信息
- 可以使用copy代替re-slice提高性能
map预分配内存
使用string.Builder效率要比直接拼接或者bytes.Buffer高
- bytes.Buffer转换为字符串时重新申请了一块空间
- string.Builder直接将底层[]byte转换为字符串类型返回
使用空结构体
空结构体实例struct{}不占据任何的内存空间 例如:实现set,我们可以考虑用到map和空结构体
性能调优实战
原则:
- 要靠数据而不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具pprof
在浏览器中打开:http://localhost:6060/debug/pprof后:
说明:
- allocs: 内存分配情况
- blocks: 阻塞操作情况
- cmdline: 程序启动命令
- goroutine: 当前所有goroutine的堆栈信息
- heap: 堆上内存使用情况
- profile: cpu占用情况
- threadcreate: 当前所有创建的系统线程的堆栈信息
- trace: 程序运行追踪信息
我遇到的一些问题:改本地代码运行结果没有变化
这是因为引用的还是远程仓库的代码,修改本地代码不会起作用。!
步骤应该为:(在terminal中输入)
- go mod init 项目名
- go mod tidy
- 修改import语句,将github.com/wolfogre/go-pprof-practice/..改成go-pprof-practice/..,将引用变成本地文件
- run main.go ,生效