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

131 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第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

img.png 在浏览器中打开:http://localhost:6060/debug/pprof后:

img_1.png 说明:

  • 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 ,生效