You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确计算Go语言Goroutine并发函数的执行时间?

关于Goroutine并发函数执行时间的正确计算方法

首先纠正你的理解误区:你当前代码计算的是函数从启动到结束的墙钟时间(实际流逝的时间),这个结果是准确的。Goroutine的调度切换确实会让它交替执行,但墙钟时间统计的是整个函数生命周期的真实耗时——不管中间被调度出去多少次,从time.Now()到time.Since(start)的时间就是函数从开始到完成的实际时间,这符合大多数场景下的“执行时间”需求。

你的现有代码存在语法错误,修正后可以正常使用:

import (
    "fmt"
    "time"
)

func timeElapsed() func() {
    start := time.Now()
    return func() {
        elapsed := time.Since(start)
        fmt.Println("函数执行耗时:", elapsed)
    }
}

func thisIsGoFunction() { // 补全(),修正语法错误
    defer timeElapsed()()

    // 你的业务代码:遍历map、使用mutex等逻辑
}

如果你需要统计的是该Goroutine实际占用CPU的时间(排除调度等待、IO等待等非CPU耗时),则需要借助系统调用或Go runtime的指标来实现。以下是基于syscall获取线程CPU时间的示例(需绑定Goroutine到线程):

import (
    "fmt"
    "runtime"
    "syscall"
    "time"
)

func getCPUTime() (user, sys time.Duration, err error) {
    var rusage syscall.Rusage
    if err := syscall.Getrusage(syscall.RUSAGE_SELF, &rusage); err != nil {
        return 0, 0, err
    }
    user = time.Duration(rusage.Utime.Nano())
    sys = time.Duration(rusage.Stime.Nano())
    return user, sys, nil
}

func timeCPUEapsed() func() {
    startUser, startSys, _ := getCPUTime()
    return func() {
        endUser, endSys, _ := getCPUTime()
        userElapsed := endUser - startUser
        sysElapsed := endSys - startSys
        fmt.Printf("用户态CPU耗时: %v, 内核态CPU耗时: %v, 总CPU耗时: %v\n", userElapsed, sysElapsed, userElapsed+sysElapsed)
    }
}

func thisIsGoFunction() {
    // 绑定Goroutine到当前线程,确保统计的是该Goroutine的CPU时间
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    
    defer timeCPUEapsed()()

    // 你的业务代码:遍历map、使用mutex等逻辑
}
  • 绑定线程(runtime.LockOSThread())会阻止Go runtime调度该线程上的其他Goroutine,仅在需要精确统计单个Goroutine的CPU时间时使用,不推荐在高并发场景下滥用。
  • 如果是统计多个Goroutine的总CPU耗时,更适合用pprof工具进行性能分析,而非在代码中硬编码统计。

内容的提问来源于stack exchange,提问作者Atharva Ajgaonkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:23:16