首页 > golang > golang可视化GMP编程
2021
01-05

golang可视化GMP编程

可视化 GMP 编程

有 2 种方式可以查看一个程序的 GMP 的数据。

方式 1:go tool trace

trace 记录了运行时的信息,能提供可视化的 Web 页面。

简单测试代码:main 函数创建 trace,trace 会运行在单独的 goroutine 中,然后 main 打印”Hello World” 退出。

trace.go

package main

import (
    "os"
    "fmt"
    "runtime/trace"
)

func main() {

    //创建trace文件
    f, err := os.Create("trace.out")
    if err != nil {
        panic(err)
    }

    defer f.Close()

    //启动trace goroutine
    err = trace.Start(f)
    if err != nil {
        panic(err)
    }
    defer trace.Stop()

    //main
    fmt.Println("Hello World")
}

运行程序

$ go run trace.go 
Hello World

会得到一个 trace.out 文件,然后我们可以用一个工具打开,来分析这个文件。

2021/01/05 16:38:01 Parsing trace...
2021/01/05 16:38:01 Splitting trace...
2021/01/05 16:38:01 Opening browser. Trace viewer is listening on http://127.0.0.1:58040

我们可以通过浏览器打开  http://127.0.0.1:58040/   网址,点击 view trace 能够看见可视化的调度流程。

图片.png

图片.png

G 信息

点击 Goroutines 那一行可视化的数据条,我们会看到一些详细的信息。

图片.png

一共有两个G在程序中,一个是特殊的G0,是每个M必须有的一个初始化的G,这个我们不必讨论。

其中 G1 应该就是 main goroutine (执行 main 函数的协程),在一段时间内处于可运行和运行的状态。

M 信息

点击 Threads 那一行可视化的数据条,我们会看到一些详细的信息。

图片.png

一共有两个 M 在程序中,一个是特殊的 M0,用于初始化使用,这个我们不必讨论。

P 信息

图片.png

G1 中调用了 main.main,创建了 trace goroutine g6。G1 运行在 P0 上,G6运行在 P1 上。

这里有两个 P,我们知道,一个 P 必须绑定一个 M 才能调度 G。

我们在来看看上面的 M 信息。

图片.png

我们会发现,确实 G6 在 P1 上被运行的时候,确实在 Threads 行多了一个 M 的数据,点击查看如下:

图片.png

多了一个 M2 应该就是 P1 为了执行 G6 而动态创建的 M2.

方式 2:Debug trace

package main

import (
    "fmt"
    "time"
)

func main() {
    for i := 0; i < 5; i++ {
        time.Sleep(time.Second)
        fmt.Println("Hello World")
    }
}

编译

$ go build trace2.go

通过 Debug 方式运行

$ GODEBUG=schedtrace=1000 ./trace2 
SCHED 0ms: gomaxprocs=2 idleprocs=0 threads=4 spinningthreads=1 idlethreads=1 runqueue=0 [0 0]
Hello World
SCHED 1003ms: gomaxprocs=2 idleprocs=2 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0]
Hello World
SCHED 2014ms: gomaxprocs=2 idleprocs=2 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0]
Hello World
SCHED 3015ms: gomaxprocs=2 idleprocs=2 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0]
Hello World
SCHED 4023ms: gomaxprocs=2 idleprocs=2 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0]
Hello World

    SCHED:调试信息输出标志字符串,代表本行是 goroutine 调度器的输出;

    0ms:即从程序启动到输出这行日志的时间;

    gomaxprocs: P 的数量,本例有 2 个 P, 因为默认的 P 的属性是和 cpu 核心数量默认一致,当然也可以通过 GOMAXPROCS 来设置;

    idleprocs: 处于 idle 状态的 P 的数量;通过 gomaxprocs 和 idleprocs 的差值,我们就可知道执行 go 代码的 P 的数量;

    threads: os threads/M 的数量,包含 scheduler 使用的 m 数量,加上 runtime 自用的类似 sysmon 这样的 thread 的数量;

    spinningthreads: 处于自旋状态的 os thread 数量;

    idlethread: 处于 idle 状态的 os thread 的数量;

    runqueue=0: Scheduler 全局队列中 G 的数量;

    [0 0]: 分别为 2 个 P 的 local queue 中的 G 的数量。


本文》有 0 条评论

留下一个回复