go包:trace调试

2023-11-13  本文已影响0人  呦丶耍脾气

1. trace说明

pprof的分析中,能够知道一段时间内的CPU占用、内存分配、协程堆栈信息。这些信息都是一段时间内数据的汇总,但是它们并没有提供整个周期内发生的事件,例如指定的Goroutines何时执行、执行了多长时间、什么时候陷入了堵塞、什么时候解除了堵塞、GC如何影响单个Goroutine的执行、STW中断花费的时间是否太长等。这就是在Go1.5之后推出的trace工具的强大之处,它提供了指定时间内程序发生的事件的完整信息,这些事件信息包括:

2. 收集trace样本

收集trace文件的方式和收集pprof特征文件的方式非常相似,有两种主要的方式

2.1 调用runtime/trace

// 创建文件
file, _ := os.OpenFile("./trace.out", os.O_APPEND|os.O_CREATE, os.ModePerm)
// 开启
if err := trace.Start(file); err != nil {
    fmt.Println("trace start err ",err)
    return
}
// 关闭
defer trace.Stop()

2.2 调用net/http/pprof

net/http/pprof库中集成了trace的接口,下例获取30s内的trace事件并存储到trace.out文件中。

curl -o trace.out http://127.0.0.1:6060/debug/pprof/trace?seconds=30

2.3 在单元测试中使用-trace

//  trace.out:是生成的文件名  test/trace_test.go:是测试文件
go test -trace trace.out test/trace_test.go

3. 分析trace样本

分析trace样本,语法格式: go tool trace trace文件

3.1 第一步: 分析文件

# 分析文件trace2.out,会生成一个链接
➜ go tool trace trace2.out
2021/11/18 19:45:53 Parsing trace...
2021/11/18 19:45:53 Splitting trace...
2021/11/18 19:45:54 Opening browser. Trace viewer is listening on http://127.0.0.1:65154

3.2 第二步:在浏览器中打开

image.png

分析维度说明

4. View trace查看跟踪

4.1 数据栏总览

image.png

含义说明:

快捷键: w(放大)、s(缩小)、a(左移)、d(右移)

4.2 某一时刻协程整体运行情况

image.png

由上图可以看出,这个时刻(946.662607): 运行中的协程数量为2、可运行的协程数量为1、等待GC的协程为0

4.3 某一时刻堆内存

image.png

4.4 某一时刻系统线程

4.5 查看垃圾回收

1.单个垃圾回收

2.查看多个垃圾回收

选中多个垃圾回收,则可查看多个垃圾回收信息

3.部分协程功能说明

4.6 查看具体协程运行信息

[图片上传失败...(image-297c6a-1680262407787)]

含义说明:

字段名 说明
Start 开始时间
Wall Duration 持续时间
Self Time 执行时间
Start Stack Trace 开始时的堆栈信息
End Stack Trace 结束时的堆栈信息
Incoming flow 输入流
Outgoing flow 输出流
Preceding events 之前的事件
Following events 之后的事件
All connected 所有连接的事件

5. 协程分析(Goroutine analysis)

5.1 详情查看


5.2 字段说明

名称 含义 耗时
Execution Time 执行时间 151µs
Network Wait Time 网络等待时间 0ns
Sync Block Time 同步阻塞时间 19s
Blocking Syscall Time 调用阻塞时间 0ns
Scheduler Wait Time 调度等待时间 24µs
GC Sweeping GC 清扫 0ns
GC Pause GC 暂停 12ms

6.用户自定义任务

6.1 代码详情

package main

import (
    "context"
    "fmt"
    "os"
    "runtime/trace"
    "sync"
)
func main() {
    file, err := os.Create("./mytask.out")
    if err != nil {
        fmt.Printf("%v\n", err)
        return
    }
    defer file.Close()
    err = trace.Start(file)
    if err != nil {
        fmt.Printf("%v\n", err)
        return
    }
    defer trace.Stop()

    // 创建自定义任务
    ctx, task := trace.NewTask(context.Background(), "myTask")
    defer task.End()
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        gn := i
        // 启动协程
        wg.Add(1)
        go func() {
            defer wg.Done()
            trace.WithRegion(ctx, fmt.Sprintf("goroutine-%d",gn), func() {
                sum := 0
                for n := 0; n < 1000000; n++ {
                    sum = sum + n
                }
                fmt.Println("sum = ",sum)
            })
        }()
    }
    wg.Wait()
    fmt.Println("run ok!")
}

6.2 查看详情

上一篇 下一篇

猜你喜欢

热点阅读