这是我参与「第三届青训营 -后端场」笔记创作活动的的第三篇笔记
预习 pprof使用 | golang pprof 实战
package main
import (
// 略
_ "net/http/pprof" // 会自动注册 handler 到 http server,方便通过 http 接口获取程序运行采样报告
// 略
)
func main() {
runtime.GOMAXPROCS(1) // 限制 CPU 使用数,避免过载
runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪,每次加锁都记录
runtime.SetBlockProfileRate(1) // 开启对阻塞操作的跟踪,每次阻塞都会记录
go func() {
// 启动一个 http server,注意 pprof 相关的 handler 已经自动注册过了
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
}
这份代码在文章中称为“炸弹”,本文实战使用pprof主要解决💣中的一下问题,CPU占用,内存占用,频繁GC,协程泄露,锁的争用,长时间阻塞。忘记内容了就去标题的超链接看吧,以下命令都有类似套路。
程序启动后在浏览器输入http://localhost:6060/debug/pprof/,会显示如下内容
之后在终端中输入的命令go tool pprof http://localhost:6060/debug/pprof/profile/xxx的xxx,都是对应的上面的allocs,goroutine,heap等等
go tool pprof http://localhost:6060/debug/pprof/heap //内存
go tool pprof http://localhost:6060/debug/pprof/allocs // GC
go tool pprof http://localhost:6060/debug/pprof/goroutine // 协程
go tool pprof http://localhost:6060/debug/pprof/mutex // 锁竞争
go tool pprof http://localhost:6060/debug/pprof/block // 阻塞
# 终端打开pprof 只记录10秒
go tool pprof -http:=8080 http://localhost:6060/debug/pprof/profile?second=10
# 查看cpu占用情况
top
# 定位函数
list xxxfunc
# 电脑中需要装有graphviz,键入web后会打开图形化分析,类似下面这样是对锁的分析
web
- top命令的界面
- pprof在浏览器中的图形界面
1. 性能优化建议(流批!~)
Benchmark
Slice| 两个性能陷阱
Get新知识,大内存未释放(应该和GC有关系)
字符串处理
// 方式一
s += str
// 方式二
var builder strings.Builder
builder.WriteString(str)
return builder.String()
// 方式三
buf := new (bytes.Buffer)
buf.WriteString(str)
return buf.String
- 使用最原始的方法每次增加时会申请新的字符串进行拷贝
- 使用strings.Builder和bytes.Buffer类似,他们底层的扩容机制,不需要每次拼接字符串时申请内存,而bytes.Buffer比strings.Builder略微慢一点的原因是在返回String时,bytes会多申请一次内存用来返回,String.Builder是直接取出底层指针里的内容
- 能不能像切片一样提前预分配好内存大小,而不用每次去扩容?确实有!~bytes.Buffer.Grow 和 strings.Builder.Grow
空结构体
实现set,将map里的value值设为空结构体类型,减少无用内存的消耗
原子操作 Atomic
2. 性能分析工具原理部分 | pprof
cpu信息的获取
heap信息的获取
Goroutine&ThreadCreate
Block&Mutex
3. 业务服务优化
建立性能评估的手段
- 服务性能的评估方式
- Benchmark
- 不同负载下性能表现差异 需要用到额外的压测工具
- 请求流量构造
- 不同参数覆盖的逻辑不同
- 线上真实流量
- 压测范围
- 单机器
- 集群
- 性能数据采集------>压测报告,火焰图
- 单机
- 集群
业务中可能会有问题的方面:比如使用库不规范;长时间消耗CPU干无意义重复的事情;非重要的事情被强制要求同步完成(比如高并发场景下的日志记录)