我正在尝试使用 rusage 测量各种函数调用的资源使用时间(用户和系统)。我发现我得到的结果大约是 10 毫秒,如 0 70000us、10000us 等。请告诉我是否有办法为 getrusage 设置精度/粒度。
我的程序很简单:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
int main(){
struct rusage usage;
struct timeval start, end;
int i, j, k = 0;
getrusage(RUSAGE_SELF, &usage);
start = usage.ru_utime;
printf("buffer check\n");
char *str = "---";
int arr[100],ctr;
for(ctr = 0;ctr<100;ctr++){
arr[ctr] = ctr + 1000;
}
for (i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++) {
k += 20;
}
}
getrusage(RUSAGE_SELF, &usage);
end = usage.ru_utime;
printf("Started at: %ld.%lds\n", start.tv_sec, start.tv_usec);
printf("Ended at: %ld.%lds\n", end.tv_sec, end.tv_usec);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
结果开始于:0.0s 结束于:0.2000000s
我添加了另一个 for 循环并得到如下结果: Started at: 0.0s Ended at: 0.7000000s 我浏览了很多以找到获得准确计时的可能方法。在 linux 源代码等中遇到了 3 个参数 getrusage,但我不确定如何使用它,因为它需要任务指针作为第一个参数。其中一个链接表明它与 linux 版本有关。无论如何,请让我知道是否有任何方法可以设置精度/粒度。如果没有,请告诉我是否有任何替代 getrusage 的方法。gettimeofDay 似乎没有提供资源使用细节,所以如果我无法设置精度,请寻找 getrusage 的实际实现。
许多操作系统不会精确计算进程所用的时间。在许多情况下,在每个上下文切换和系统调用上读取时钟的成本太高,在其他情况下,硬件甚至可能没有允许您以任何精度计时的时钟。
一种非常常用的计数方法getrusage是使用 100Hz(最常见的是 100Hz,尽管 64Hz 和 1024Hz 也很常见)定时器中断,用于对中断时系统上发生的情况进行采样。因此,内核每秒 100 次检查当前正在运行的内容和位置(ru_utime 的用户空间或 ru_stime 的内核空间)并递增计数器。然后该计数器被解释为您的程序运行了 10 毫秒。
您可以clock_gettime在您的系统上进行试验,看看它是否有每个进程的计数器,有时这些计数器可能比getrusage计数器更精确。但我不会抱太大希望,如果 10 毫秒分辨率是最好的getrusage,很可能不会clock_gettime有更好的分辨率或根本没有任何每进程时钟。
如果操作系统中的时钟不足以满足您的测量,您唯一的选择是重复测试运行几分钟,并将获得的结果除以运行次数。
更精确的事实gettimeofday并没有多大意义。gettimeofday可能相对昂贵。考虑一下内核必须做的工作才能准确跟踪进程的用户和系统时间。每次进行系统调用时,都必须记录两次时间戳(一次用于系统调用开始,一次在结束时),以便跟踪您使用了多少系统时间。为了跟踪用户时间,每次系统切换到另一个进程时,您都需要时间戳。许多系统确实会跟踪第二个,但不会跟踪第一个,因为系统调用比进程上下文切换更常见(这就是为什么我建议检查,clock_gettime因为它可以有一个计时器来累积进程的总系统和用户时间)。
现代系统中的时钟非常烦人,因为即使获取时间戳是最常见的系统调用之一,我们仍然经常需要在缓慢的总线中进行拖网并进行大量锁定才能获取它们。其他解决方案(例如 CPU 上的周期计数器)已被使用,但众所周知,这些解决方案不准确,因为它们可能在 CPU 之间不同步,可能具有可变频率,可能会在操作系统的控制之外停止等等,并且您需要知道您的 CPU 的确切型号,以便能够可靠地使用它们。操作系统有很多启发式方法来确定要使用哪些时钟,但这可能意味着两台几乎相同的机器之间存在巨大差异。一个可能会得到一个亚纳秒精度的周期计数器,需要一条指令来读取,而另一个则需要通过 ISA 总线到达具有微秒精度或更差的 30 年历史的芯片设计,这需要数千个周期来读取。