关于C#:如何测量一个程序的用户/系统CPU时间?

How to measure user/system cpu time for a piece of program?

在经典APUE(UNIX环境中的高级编程)的3.9节中,作者测量了他的示例程序中消耗的用户/系统时间,该程序针对不同的缓冲区大小(I / O读/写程序)运行。

结果表有点像(所有时间都以秒为单位):

1
2
3
4
5
BUFF_SIZE  USER_CPU   SYSTEM_CPU  CLOCK_TIME  LOOPS
1          124.89     161.65      288.64      103316352
...        
512        0.27       0.41        7.03        201789
...

我很好奇并且真的想知道如何测量一个程序的USER / SYSTEM CPU时间?

在这个例子中,CLOCK TIME是什么意思以及如何衡量它?

显然,它不仅仅是用户CPU时间和系统CPU时间的总和。


您可以使用*nix下的time命令轻松测量程序的运行时间:

1
2
3
4
5
$ time myprog

real        0m2.792s
user        0m0.099s
sys         0m0.200s

realCLOCK_TIME指的是挂钟时间,即从程序开始到完成所用的时间,甚至包括内核上下文切换时其他进程占用的时间片。它还包括任何时间,进程被阻止(在I / O事件等)

userUSER_CPU指的是在用户空间中花费的CPU时间,即在内核之外。与real时间不同,它仅指特定进程占用的CPU周期。

sysSYSTEM_CPU指的是在内核空间中花费的CPU时间(作为系统调用的一部分)。同样,这只是计算代表进程在内核空间中花费的CPU周期,而不是任何时候被阻塞。

time实用程序中,usersys是从times()wait()系统调用计算的。 real通常使用在程序开始和结束时使用gettimeofday()系统调用收集的2个时间戳中的时间差来计算。

您可能想知道的另一件事是real != user + sys。在多核系统上,usersys或它们的总和可以很容易地超过real时间。


部分答案:

好吧,CLOCK_TIME与时钟所示的时间相同,时间在所谓的"真实世界"中传递。

测量的一种方法是使用gettimeofday POSIX函数,它将时间存储到调用者的struct timeval,包含UNIX秒字段和微秒字段(实际精度通常更低)。在典型的基准代码中使用它的示例(忽略错误等):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);

do_operation_to_measure();

gettimeofday(&tv2, NULL);

// get difference, fix value if microseconds became negative
struct timeval tvdiff = { tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec };
if (tvdiff.tv_usec < 0) { tvdiff.tv_usec += 1000000; tvdiff.tv_sec -= 1; }

// print it
printf("Elapsed time: %ld.%06ld
"
, tvdiff.tv_sec, tvdiff.tv_usec);