Golang的trace性能分析
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
一、trace概述
上一篇是pprof
的性能分析通过pprof
找到我们服务中的瓶颈点来进行优化。Golang的pprof性能分析
一般我们使用pprof
的profile
来分析服务的性能主要是CPU
方面的耗时和调用链路等。但是光靠profile
是不够的细节方面还是要使用trace
分析并发和阻塞事件,goroutine
的调度和GC
情况。
相比profile
通过trace
我们能看到什么呢
1、程序运行中的goroutine数量分布
2、GC的频率和Heap的占比
3、goroutine的调度和运行阻塞情况
二、trace的使用方式
代码中trace采集
import (
"os"
"runtime/trace"
)
func main() {
trace.Start(os.Stderr)
defer trace.Stop()
}
// 生成trace
go run main.go 2> trace.out
通过pprof采集
// trace采样
浏览器下载 http://127.0.0.1:6060/debug/pprof/trace?seconds=20
命令行采样 curl http://127.0.0.1:6060/debug/pprof/trace\?seconds\=20 > trace.out
// 运行采样的trace文件,会自动打开浏览器页面
go tool trace trace.out
三、trace分析细节
trace的web界面
参考Go 大杀器之跟踪剖析 trace
https://eddycjy.gitbook.io/golang/di-9-ke-gong-ju/go-tool-trace
View trace查看跟踪
Goroutine analysisGoroutine 分析
Network blocking profile网络阻塞概况
Synchronization blocking profile同步阻塞概况
Syscall blocking profile系统调用阻塞概况
Scheduler latency profile调度延迟概况
User defined tasks用户自定义任务
User defined regions用户自定义区域
Minimum mutator utilization最低 Mutator 利用率
trace中需要关注的
关注GC的频率
GC
的频率过大会导致大量的资源用于GC
阶段影响程序性能。另外要关注Heap
的释放情况Heap
经过GC
之后不释放那就需要关注内存泄漏问题了。内存泄漏大部分是查看goroutine
释放和服务占用内存情况可以参考Golang的pprof性能分析
关注goroutine调度情况
鼠标放着不动w
是放大s
是缩小。一直放大可以查看具体goroutine
的执行细节
关注goroutine的数量
理想情况
1、GC次数适中要多或者太小都不行
2、goutinue数量不会突增或者持续增加
3、goroutine的调度密集且有规律
下面这个就是GC
过于频繁的例子。goroutine
的调度还是不错的有规律且密集
四、GC分析
当前服务GC情况
可以看到GC
很频繁。查看监控发现服务内存只用到了几十M.
这种情况只能手动改动GC
的阈值了。
GOGC 变量设置初始垃圾收集目标百分比。当新分配的数据与上次收集后剩余
的实时数据的比率达到此百分比时将触发收集。
默认值为 GOGC=100。
比如上次gc之后剩余10M,那么下次GC的阈值就是10M+10*100% = 20M
设置GOGC
// 调整gc阈值的源码
func readGOGC() int32 {
p := gogetenv("GOGC")
if p == "off" {
return -1
}
if n, ok := atoi32(p); ok {
return n
}
return 100
}
设置环境变量GOGC
然后查看trace
:
设置GOMEMLIMIT
程序中GOGC
设置成3000
实际上内存利用率还是很低只有200M
,服务给定的资源是4G
GOMEMLIMIT 设置GC的阈值(go 1.19提供)设置为服务限定资源的一半
GOGC=off : 关闭自动GC。
效果如下
GC阈值的讨论
GC的特点
1、当 GC 在标记和清除阶段之间转换时短暂的 stop-the-world 暂停
2、调度延迟因为在标记阶段GC占用了25%的CPU资源
3、用户 goroutines 协助 GC 响应高分配率
4、当 GC 处于标记阶段时指针写入需要额外的工作并且
5、运行的 goroutines 必须暂停以扫描它们的根。
过多的GC
会占用CPU
和goroutine
的资源。但是过少的GC
会导致每次GC
的stw
时间变长因为要标记和清楚的内存过多。因此GC
阈值设置多大也是个选择题。
五、goroutinue分析
goroutine概览
通过放大可以看到goroutine
的状态有Dedicated
的有Idle
的。还有处于mark
标记状态的有sweep
的。
GC
的三个主要阶段mark
标记、sweep
清扫和 scan
扫描。好了跟八股文完美对上了。
红框中还有大名鼎鼎的STW
。
标记阶段会将大概25%(gcBackgroundUtilization)的P用于标记对象
逐个扫描所有G的堆栈执行三色标记在这个过程中所有新分配的对象
都是黑色被扫描的G会被暂停扫描完成后恢复这部分工作叫
后台标记(gcBgMarkWorker)。
这会降低系统大概25%的吞吐量比如MAXPROCS=6那么GC
P期望使用率为6*0.25=1.5这150%P会通过专职(Dedicated)/
兼职(Fractional)/懒散(Idle)三种工作模式的Worker共同来完成。
Sync block耗时分析
从trace
的 goroutine analysis
点进去查看主要的goroutine
列表。
点进去就可以查看具体的goroutine
执行情况。
点击查看goroutine
发现trace
如下
看起来146210
这个goroutine
进入了专职Dedicated
GC处理工作模式。查看几个Sync block
耗时比较长的发现都是在GC
的时候goroutine
开始处理GC
而暂停处理业务等GC
结束才会继续执行业务。 在优化过GC
之后Sync block
耗时大幅度下降。
Scheduler wait耗时分析
大量的Scheduler wait
如下
关于调度我们都知道Go
是GMP
模型的调度那么P
的大小和goroutine
的数量都会影响到调度性能。推荐使用uber
的自动设置GOMAXPROCS
的库。
uber开源的自动设置maxprocs的库
注意 在服务分配的CPU
不足1
核的情况下使用automaxprocs
没什么提升。反而在多核的情况下需要通过这个库来设置最佳的GOMAXPROCS
end
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |