5.11 青训营Day03 高质量编程和pprof的使用

109 阅读3分钟

高质量编程

正确可靠,简洁清晰

编程原则

  • 简单性
  • 可读性
  • 生产力

编码规范

  • 代码格式
  • 注释
  • 命名
  • 控制流程
  • 错误和异常处理

代码格式

gofmt会自动帮你整理格式

goimports (gofmt+依赖包管理),自动增删依赖包,将依赖包按照字母顺序排序分类

注释

作用,怎么work的,为什么要(提供上下文),什么情况会有异常/错误

命名

缩略词需要全部大小,如果不想暴露外部,需要统一小写,不要仅仅首字母小写

函数命名不需要携带包名的上下文信息,例如severice层的方法,在controller层调用是service.XXXFunc

image.png 包名使用小写,不含大写字母和下划线。不要与系统库重名,使用单数形式,尽量不要占用常用变量名

控制流程

减少嵌套,尽量展开

错误和异常处理

简单错误

  • 指仅出现一次的错误,在其他地方不需要捕获该错误
  • 优先使用errors.New 来创建匿名变量来直接表示简单错误
  • 有格式化需求可以使用fmt.Errorf

错误的wrap和unwrap

  • 错误的wrap可以让一个error嵌套一个error
  • fmt.Errorf 使用 %w 关键字来讲一个错误关联至错误链中

错误判定

  • errors.Is可以帮助判断错误(链)上是否有特定错误
  • errors.As可以帮助取特定类型error内容

panic,recover

不建议业务代码中使用panic,recover只能在被defer的函数中使用,嵌套无法生效

性能调优

go test -bench=. 建议在命令行使用,在vscode的console里使用output不全

goos: windows
goarch: amd64
pkg: go-project-example-day02/test
cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
BenchmarkFib20-8   	   48744	     24838 ns/op	       0 B/op	       0 allocs/op
PASS

优化建议

  • slice尽可能预分配内存
  • 在已有切边上创建切片,新的切片引用老的切片,导致老切片内存无法被释放。所以建议用copy 替代 重新切片
  • stringbuilder, stringbuffer 来字符串拼接
  • 使用空结构体,可做map值占位
  • 使用系统atomic包

原则

  • 依靠数据,不靠猜测
  • 定位最大瓶颈
  • 不要过早优化
  • 不要过度优化

工具pprof

准备工作

将pprof handler注册到http server中

import (
    "log"
    "net/http"
    _ "net/http/pprof"  // 注册
    "github.com/EDDYCJY/go-pprof-example/data"
)

指标含义

image.png Flat == Cum, 函数中没有调用其他函数 Flat == 0, 函数中只有其他函数调用

image.png

cpu占用查看

go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 随即可以进行命令行的交互,如top

(pprof) top
Showing nodes accounting for 6.33s, 99.84% of 6.34s total
Dropped 1 node (cum <= 0.03s)
      flat  flat%   sum%        cum   cum%
     6.33s 99.84% 99.84%      6.34s   100%  github.com/wolfogre/go-pprof-practice/animal/muridae/mouse.(*Mouse).Steal (inline)
         0     0% 99.84%      6.34s   100%  github.com/wolfogre/go-pprof-practice/animal/muridae/mouse.(*Mouse).Live
         0     0% 99.84%      6.34s   100%  main.main
         0     0% 99.84%      6.34s   100%  runtime.main

如果命令行键入web会跳转网页 可以看到CPU占用大户

image.png

再使用list,可以帮助更精确定位

image.png

heap堆内存占用情况

带上选项-http=:8080会打开图形化界面

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap" 会弹窗

image.png

选中VIEW->Source可以进一步进行排查,如图

image.png

修正过后,再次打开,好像不错

image.png

但是,刚刚我们仅是在 inuse_space(应用程序的常驻内存占用情况)中看到的,有没有可能一些内存是临时分配的呢(alloc_space)

image.png

切换到alloc_space后,我们发现有的

image.png

goroutine

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine" 然后VIEW->Flame Graph

可以看到wolf.Drink方法占用了很多CPU时间

image.png

切换到Source,然后搜索wolf可以找到:然后进行修改

image.png

mutex 锁

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"

block 阻塞

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"

工具pprof原理(略,详见ppt)

业务案例

流程

  1. 确定性能评估手段

  2. 分析数据,定位性能瓶颈

  3. 重点优化项改造

    要保证正确性,对比优化前后返回数据区别

  4. 验证