我需要衡量go中插件的执行时间(cpu成本),我们可以将插件视为函数,可能同时运行许多goroutine。更准确地说,执行时间应排除空闲时间(goroutine等待时间),仅应cpu获取时间(当前goroutine的时间)。 就像:
go func(){
// this func is a plugin
** start to record cpu acquire time of current func/plugin/goroutine **
** run code **
** stop to record cpu acquire time of current func/plugin/goroutine **
log.Debugf("This function is buzy for %d millisecs.", cpuAcquireTime)
** report cpuAcquirTime to monitor **
}()
在我的情况下,很难进行单元测试来测量功能,很难去耦代码。
我在搜索google和stackoverflow时没有发现任何线索,有什么解决方案可以满足我的需求,并且是否需要太多资源?
答案 0 :(得分:1)
对于后来像我一样偶然发现此问题的人,您实际上可以使用内置的syscall.Getrusage而不是Cgo。一个例子看起来像
func GetCPU() int64 {
usage := new(syscall.Rusage)
syscall.Getrusage(syscall.RUSAGE_SELF, usage)
return usage.Utime.Nano() + usage.Stime.Nano()
}
我将调用进程(RUSAGE_SELF)的Utime(用户CPU时间)和Stime(系统CPU时间)都转换为纳秒后相加。 man 2 getrusage
对此系统调用有更多信息。
syscall.Timeval的文档建议Nano()返回自Unix纪元以来的时间(以纳秒为单位),但是在我的测试和实施中,它看起来实际上仅返回CPU时间(以纳秒为单位),而不是自从Unix时代。
答案 1 :(得分:0)
Go中没有内置的方法来测量CPU时间,但是您可以通过特定于平台的方法来进行测量。
例如,在POSIX系统(例如Linux)上,将 clock_gettime
与 CLOCK_THREAD_CPUTIME_ID
用作参数。
类似地,您可以使用CLOCK_PROCESS_CPUTIME_ID
来测量进程CPU时间,并使用CLOCK_MONOTONIC
来计算经过时间。
示例:
package main
/*
#include <pthread.h>
#include <time.h>
#include <stdio.h>
static long long getThreadCpuTimeNs() {
struct timespec t;
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t)) {
perror("clock_gettime");
return 0;
}
return t.tv_sec * 1000000000LL + t.tv_nsec;
}
*/
import "C"
import "fmt"
import "time"
func main() {
cputime1 := C.getThreadCpuTimeNs()
doWork()
cputime2 := C.getThreadCpuTimeNs()
fmt.Printf("CPU time = %d ns\n", (cputime2 - cputime1))
}
func doWork() {
x := 1
for i := 0; i < 100000000; i++ {
x *= 11111
}
time.Sleep(time.Second)
}
输出:
CPU time = 31250000 ns
请注意输出以纳秒为单位。因此,这里的CPU时间为0.03秒。