golang 的服务调优大体需要从cpu, heap,gc入手。
cpu分析是从抽样程序里各个模块的运行效率,单位是ms
heap分析是分析抽样程序各个模块的内存损耗, 单位是 MB
gc分析是记录gc时的一些样本状态,比如gc的次数,gc时对象数量,gc后对象数量,堆大小等
代码
一.GC
执行
GODEBUG=gctrace=1 go run main.go 2>xx.log
,标准输出流是GODEBUG=gctrace=1 go run main.go
,打印至控制台
会在同路径下生成 xx.log,内含gc信息
解释:
二. cpu分析
执行
go run main.go --cpuprofile=cpu.prof
会在当前路径下生成cpu.prof 文件,然后执行
go tool pprof main.go cpu.prof
进入cpu分析模块。
top10
消耗前10
web
web展现
其它命令不介绍了。
三. heap分析
执行
go run main.go --memprofile=mem.prof
go tool pprof main.go mem.prof
top10
web
所有效果和cpu类似,只是单位从ms 换成了MB
四. 逃逸分析
执行
go build -gcflags '-m -l' main.go
或者 go build -gcflags ‘-m -m’ main.go
前者消除内联了,
go build -gcflags '-m -l' main.go
-l 一个,表示消除内敛
go build -gcflags '-m -l -l' main.go
-l 两个 ,表示内联级别比默认强
go build -gcflags '-m -l' main.go
-l 3个,强内敛,二进制包体积变大,但是不稳定,可能有bug
4就不讨论了,推荐用0个,默认,或者2个,高内敛
先说几个结论:
1.魔术字符串 var a ="",会发生逃逸.
2.log和fmt会发生逃逸,返回指针类型的函数,会逃逸。
3.传递指针类型的变量不会逃逸
逃逸的后果,就是对象的寿命变长,对象数量居高不下,gc频率变高,stop the world变长。
以上, cpu,heap, gc, 逃逸, 就是我们需要优化的几个方向。
基于程序代码,做了以上优化以后,如果还遇到瓶颈,还有一些其它调优手段。
linux
cat /proc/cpuinfo| grep "processor"| wc -l
查看逻辑核数,将一些代理如nginx,haproxy的worker设置成该数量
ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head
查看高cpu,mem消耗的pid,关掉一下不必要的。