这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
Go 语言 - 性能优化指南
课程目标: 学习Go项目性能优化工具的使用方法
字符串处理
使用Strings.Builder
在处理字符串拼接的过程中,有三种处理方式 :使用 + ,strings.Builder , bytes.Buffer
其中,使用 + 拼接性能最差,strings.Builder , strings.Buffer 相近,strings.Builder 更快
分析:
- 字符串在
Go语言中是不可变类型,占用内存大小是固定的 - 使用
+每次都会重新分配内存 strings.Builder,bytes.Buffer底层都是[]byte数组- 内存扩容策略,不需要每次拼接重新分配内存
空结构体
使用空结构体节省内存
空结构体 struct{} 不占用任何的内存空间,可以在任何场景下当做占位符来使用
使用空结构体实现 Set
我们在实现 Set 的时候,可以考虑使用 map 来替代。替代的时候,我们只需要只用 map 的键,而不需要值。即使值复制为 布尔类型,都会占用一个字节的内存。
atomic 包
实现多线程计数器的时候,除了给公共变量加锁以外,还可以使用 atomic 来实现计数器
分析:
- 锁的实现是通过操作系统来实现的,属于系统调用
atomic操作是通过硬件来实现的,效率比直接加锁高sync.Mutex应该用来保护一段代码逻辑,不仅仅用来保护一个变量- 对于非数值操作,可以使用
atomic.Value, 可以承载一个interface {}
Go 性能优化分析工具
pprof
项目实战
cpu
go tool pprof "http://localhost:6060/debug/pprof/profile?second=10" # 这里只采集10s
top命令
进入 pprof 界面后,输入 top 就可以得到函数占用资源的多少
| 指令 | 含义 |
|---|---|
| flat | 当前函数本身的执行耗时 |
| flat% | flat 占 CPU 总时间的比例 |
| sum% | 上面每一行的 flat% 的总和 |
| cum | 指当前函数本身加上其调用函数的总耗时 |
| cum% | cum 占CPU 总时间的比例 |
观察上图可以看到,有的函数 flat == cum 有的函数 flat == 0
flat == cum: 说明函数中没有调用其他函数,flat == 0: 说明该函数中只有其他函数的调用
list 命令
由上图可知,消耗 CPU 资源最大的函数是排在第一位的 Eat 函数,此时我们可以使用list 函数对它进行查看
可以看到代码中第 行这个 for 循环使用了 的 CPU,耗时最长。
web 命令
使用 web 命令可以看到程序执行过程中的可视化
内存
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
可以看到 Mouse 占用的内存最高
通过 VIEW 中够可以看到代码来源,火焰图等图标分析
在 SAMPLE 中我们还可以看到四个指标:
- alloc_objects : 程序累计申请的对象数
- alloc_space : 程序累计申请的内存大小
- inuse_objects : 程序当前持有的对象数
- inuse_space : 程序当前占用的内存大小
goroutine - 协程
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
进入后点击火焰图查看协程的 CPU 占用情况
- 从上到下表示每个协程的调用顺序
- 每一块代表一个函数,块越长表示占用
CPU的时间越长 - 火焰图是动态的,可以点击块进行分析
切换到 Source 视图,搜索排在第一的 wolf 函数
可以看到,该函数每次开启 个协程,且等待 后才退出,占用非常多的 CPU
Mutex - 锁
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
仍然和前面一样,查看哪一个函数调用最多的锁,然后切换到 source 视图,查看源代码
block - 阻塞
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
仍然和前面一样,查看哪一个函数阻塞时间最长,然后切换到 source 视图,查看源代码
小细节
在使用 top 命令的时候,它会自动过滤节点,将小于某个时间段的节点自动丢弃,图中就将运行时长小于 0.04s 的节点扔掉了,共扔掉了 72 个,如果想要详细分析这些节点,可以进入网页可视化图中查看。