一、GODEBUG参数 特别方便,无需下载第三方工具,无需修改程序 代码
分析协程调度情况
https://segmentfault.com/a/1190000020108079
二、Trace
特点
无需下载第三方工具,需要修改程序代码
https://segmentfault.com/a/1190000019736288
如何用
修改代码,加入trace
import (
"os"
"runtime/trace"
)
func main() {
trace.Start(os.Stderr)
defer trace.Stop() //一定要这一行执行后才会有trace文件
ch := make(chan string)
go func() {
ch <- "EDDYCJY"
}()
<-ch
}
生成跟踪文件:
$ go run main.go 2> trace.out // 运行生成追踪文件
分析追踪文件
$ go tool trace trace.out // 会启动浏览器,展示网页版分析报告
分析结果说明
![image-20210621110611559](/Users/linxuesong/Library/Application Support/typora-user-images/image-20210621110611559.png)
栗子
分析结果
实例1: 如何分析程序耗时时间长—Scheduler latency profile-调度延迟概况
多协程生成随机数据,随机数据做参数访问
var wg sync.WaitGroup // main等待所有goroutine结束
func CallGetUserInfoDbatchGoVersion() {
rand.Seed(time.Now().UnixNano()) // 使用rand生成随机种子,**之后性能分析我们会发现这个地方有问题**
uidcnt := rand.Intn(50) // 使用随机种子生成50以内随机数 **之后性能分析我们会发现这个地方有问题**
SCFCALL(uidcnt) // 使用生成的随机数做参数远程调用,具体处理逻辑忽略
}
func main() {
for j:=0;j<100;j++ {
wg.Add(1)
go CallGetUserInfoDbatchGoVersion() // 开启多goroutine
}
wg.Wait()
log.Println("执行完毕")
}
对上面代码加上trace的分析
import "runtime/trace"
var wg sync.WaitGroup // main等待所有goroutine结束
func CallGetUserInfoDbatchGoVersion() {
rand.Seed(time.Now().UnixNano()) // 使用rand生成随机种子,**之后性能分析我们会发现这个地方有问题**
uidcnt := rand.Intn(50) // 使用随机种子生成50以内随机数
SCFCALL(uidcnt) // 使用生成的随机数做参数远程调用,具体处理逻辑忽略
}
func main() {
trace.Start(f)
defer trace.Stop() // 注意一定要执行了trace.Stop之后才会生成分析报告
for j:=0;j<100;j++ {
wg.Add(1)
go CallGetUserInfoDbatchGoVersion() // 开启多goroutine
}
wg.Wait()
log.Println("执行完毕")
}
结果报告中“Scheduler latency profile-调度延迟概况”如下
可以看到锁耗时占用到了77%,看调用来自Seed(*Rand),定位到耗时函数的位置后,分析这个函数
func Seed(seed int64) { globalRand.Seed(seed) } // 使用了全局对象globalRand,这个对象是lockedSource,每次使用前会加锁,导致每个go routin竞争锁
func Intn(n int) int { return globalRand.Intn(n) } // 使用全局对象,多routine会有所得竞争
解决方案:正对每个go routine生成单独的Rand对象rngSource
func CallGetUserInfoDbatchGoVersion() {
r := rand.New(rand.NewSource(time.Now().UnixNano())) // 全局对象替换成创建本地对象
uidcnt := r.Intn(50) // 使用随机种子生成50以内随机数 // 全局对象替换成本地对象
SCFCALL(uidcnt) // 使用生成的随机数做参数远程调用,具体处理逻辑忽略
}
修改后的性能分析截图–整体耗时缩短,而且不会在随机数这里有长耗时:
三、PProf
需要下载第三方工具,需要修改程序代码
https://segmentfault.com/a/1190000016412013
使用举例
分析结果