这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记
3.1 高质量编程
3.1.1 高质量编程简介
高质量指:
各种边界条件是否考虑完备
异常情况处理,稳定性保证
易读易维护
3.1.2 编码规范
1、代码格式:
①使用gofmt自动格式化代码
②使用goimports管理依赖包
2、注释
①解释代码作用
②解释代码如何做的
③解释代码实现的原因
④解释代码什么情况会出错
3、命名规范
①变量
缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
例如:使用ServeHTTP而不是ServeHttp
使用XMLHTTPRequest或者xmlHTTPRequest
变量距离其被使用的地方越远,则需要携带越多的上下文信息,如在for循环遍历中使用 i 即可,因为它仅在当前for中有效
②函数
函数名不携带包名的上下文信息,因为包名和函数名总是成对出现
函数名尽量简短
③包
只由小写字母组成。不包含大写字母和下划线等字符
简短并包含一定的上下文信息。例如schema、task等
不要与标准库同名,如不要使用sync或者strings
4、控制流程
①避免嵌套
②尽量保持正常代码路径为最小缩进
5、错误和异常处理
①简单错误
②复杂错误
③错误判定
④panic(不建议在业务中使用,用error即可)和recover
3.1.3 性能优化建议
3.1.3.1 使用标准库的BenchMark基准测试测试性能
使用命令go test -bench=. -benchmem可得到以下的结果
3.1.3.2 slice
①尽可能在使用make()初始化切片时就设置好容量大小
从切片的底层原理去分析:这样可以减少切片自己扩充容量的次数,提升性能
②在已有切片上创建切片,会复用原来的底层数组。在已有的大切片上创建小切片,会浪费大底层数组,因此建议先make一个小切片,再将大切片中需要的数据copy到小切片中
3.1.3.3 map
预分配内存,同上面slice一样
3.1.3.4 string
字符串拼接的性能。常见的字符串拼接有三种方法:性能最快的是strings.Builder
原因是string在go中是不可变类型,占用内存大小是固定的,使用+来拼接的话每次都会重新分配内存;而strings.Builder底层是[]byte数组,有内存扩充策略
3.1.3.5 atomic包
在多线程(不是goroutine)编程中,如何保证多线程安全且性能够好呢?
下图例子是实现一个多线程计数器,使用atomic而不是锁能提升性能
3.2 性能调优实战
3.2.1 性能调优简介
依靠数据而不是猜测
优化最大瓶颈而不是细枝末节
不要过早过度优化
3.2.2 性能分析工具pprof实战
pprof是可视化的分析性能和分析数据的工具,可以分析应用在什么地方耗费了多少CPU、多少Memory、goroutine阻塞的位置、互斥锁分析
3.2.2.1 pprof功能简介
3.2.2.2 pprof排查实战
blog:github.com/eddycjy/blo…,pprof简介
code:github.com/wolfogre/go…,pprof项目实战
blog:blog.wolfogre.com/posts/go-pp…,pprof项目实战
操作步骤:
①在goland中运行上面code中的main.go
②浏览器打开网址 http://localhost:6060/debug/pprof/ ,页面如下
页面上展示了可用的程序运行采样数据,下面也有简单说明,分别是: allocs:内存分配情况 block:阻塞操作情况 cmdline:程序启动命令及参数 goroutine:当前所有goroutine的堆栈信息 heap:堆上内存使用情况(同alloc) mutex:锁竞争操作情况 profile:CPU占用情况 threadcreate:当前所有创建的系统线程的堆栈信息 trace:程序运行跟踪信息
在浏览器点击每个标签,展示的采样数据可读性很差,我们需要借助 go tool pprof 命令来阅读数据,这个命令是 go 原生自带的,所以不用额外安装
我们只需关注①CPU(profile)、②内存(heap)、③协程(goroutine)、④锁(mutex)、⑤阻塞(block)
1、分析CPU占用过高的问题,在cmd或者git bash输入以下命令,即可采集10s内的数据,并进入pprof环境下
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
在pprof环境下输入topN(N指展示占用最多资源的前N个,默认是10个),即可查看占用CPU最高的函数
top
不难发现tiger.Eat()占用了最多的资源,因为找到定位后我们可以去优化它。某些行Flat=Cum说明该函数中没有调用其他函数,某些行Flat=0说明该函数中只调用了其他函数
在pprof环境下输入list Eat,便可查看Eat这个函数每一行执行时占用的CPU时间
list Eat
在pprof环境下输入web(前提是已安装Graphviz),便能自动在浏览器打开,可视化地查看函数调用图以及占用资源情况
web
最后,输入q退出pprof环境
q
2、分析内存占用过高的问题,操作和分析CPU一样,这里用一种别的方法来查看资源占用情况,会自动打开网站来查看 http://localhost:8080/ui/
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
VIEW中可切换多种方式查看
3、分析协程使用情况,操作和分析CPU一样
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
4、分析锁的竞争情况,操作和分析CPU一样
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
5、分析阻塞情况,操作和分析CPU一样
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
3.2.2.3 pprof的采样过程和原理
留到面试前才看,现在看了也忘
3.2.3 性能调优案例
3.2.3.1 业务服务优化
建立服务性能评估手段,如benchmark
分析性能数据,定位性能瓶颈,如pprof
重点优化项改造
优化效果验证
3.2.3.2 基础库优化
3.2.3.3 Go语言优化
\