9

我正在用 GO 重写一个旧系统,在旧系统中我正在测量系统负载平均值,以了解是否应该增加线程池中的线程数。

在 go 中,人们不使用线程池或 goroutine 池,因为启动 goroutine 非常便宜。但是仍然运行太多 goroutine 效率较低,仅足以将 cpu 使用率保持在 100% 附近

因此,有没有办法知道有多少 goroutine 准备好运行(未阻塞)但当前未运行。或者有没有办法获得预定的可运行goroutine“运行队列”的数量。

4

2 回答 2

10

查看runtime/pprof 包

要打印“所有当前 goroutines 的堆栈跟踪”,请使用:

pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)

要打印“导致同步原语阻塞的堆栈跟踪”,请使用:

pprof.Lookup("block").WriteTo(os.Stdout, 1)

您可以将这些与运行时包中的功能结合起来,例如runtime.NumGoroutine获得一些基本报告。

这个例子故意创建了许多阻塞的 goroutine 并等待它们完成。它每 5 秒打印block一次 pprof 配置文件的输出,以及仍然存在的 goroutine 的数量:

package main

import (
    "fmt"
    "math/rand"
    "os"
    "runtime"
    "runtime/pprof"
    "strconv"
    "sync"
    "time"
)

var (
    wg sync.WaitGroup
    m  sync.Mutex
)

func randWait() {
    defer wg.Done()
    m.Lock()
    defer m.Unlock()
    interval, err := time.ParseDuration(strconv.Itoa(rand.Intn(499)+1) + "ms")
    if err != nil {
        fmt.Errorf("%s\n", err)
    }
    time.Sleep(interval)
    return
}

func blockStats() {
    for {
        pprof.Lookup("block").WriteTo(os.Stdout, 1)
        fmt.Println("# Goroutines:", runtime.NumGoroutine())
        time.Sleep(5 * time.Second)
    }
}

func main() {
    rand.Seed(time.Now().Unix())
    runtime.SetBlockProfileRate(1)
    fmt.Println("Running...")
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go randWait()
    }
    go blockStats()
    wg.Wait()
    fmt.Println("Finished.")
}

我不确定这是否是你所追求的,但你可以修改它以满足你的需要。

操场

于 2013-11-01T01:03:49.510 回答
2

有没有办法知道有多少 goroutine 准备好运行(未阻塞)但当前未运行。?

您将能够(2014 年第 4 季度/2015 年第 1 季度)尝试和可视化这些 goroutine,正在开发新的跟踪器(2014 年第 4 季度):Go Execution Tracer

跟踪包含:

  • 与 goroutine 调度相关的事件
    • goroutine 开始在处理器上执行,
    • 同步原语上的 goroutine 阻塞,
    • 一个 goroutine 创建或解除阻塞另一个 goroutine;
  • 网络相关事件
    • 网络 IO 上的 goroutine 块,
    • goroutine 在网络 IO 上被解锁;
  • 系统调用相关事件
    • 一个 goroutine 进入系统调用,
    • goroutine 从系统调用返回;
  • 垃圾收集器相关事件
    • GC 启动/停止,
    • 并发扫描开始/停止;和
  • 用户事件

“处理器”是指一个逻辑处理器,单位为GOMAXPROCS.
每个事件都包含事件 id、精确的时间戳、操作系统线程 id、处理器 id、goroutine id、堆栈跟踪和其他相关信息(例如,未阻塞的 goroutine id)。

https://lh5.googleusercontent.com/w0znUT_0_xbipG_UlQE5Uc4PbC8Mw1duHRLg_AKTOS4iS6emOD6jnQvSDACybOfCbuSqr2ulkxULXGOBQpZ2IejPHW_8NHufqmn8q5u-fF_MSMCEgu6FwLNtMvowbq74nA

于 2014-10-29T20:16:31.170 回答