使用GO时如何测量系统过载

时间:2013-11-01 00:16:17

标签: multithreading performance go scalability

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

在go中,人们不使用线程池或goroutine池,因为启动goroutine非常便宜。 但仍然运行太多的goroutine效率低于足以使cpu使用率接近100%

因此有一种方法可以知道有多少goroutine准备运行(未阻止)但当前没有运行。或者有没有办法获得计划的可运行的goroutine“运行队列”的数量。

2 个答案:

答案 0 :(得分:10)

查看runtime/pprof package

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

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

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

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

您可以将这些功能与runtime package中的功能(例如runtime.NumGoroutine)结合使用,以获得一些基本报告。

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

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.")
}

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

Playground

答案 1 :(得分:2)

  

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

您将能够(2014年第4季度/ 2015年第1季度)尝试使用新的示踪剂(2014年第4季度)尝试可视化这些goroutine:Go Execution Tracer

  

跟踪包含:

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

由&#34;处理器&#34;我指的是一个逻辑处理器,单位为GOMAXPROCS   每个事件包含事件ID,精确时间戳,OS线程ID,处理器ID,goroutine id,堆栈跟踪和其他相关信息(例如,未阻止的goroutine id)。

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