我正在尝试使用 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;
}
结果
开始于:0.0s
结束于:0.2000000s
我添加了另一个 for 循环并得到如下结果:
开始于:0.0s
结束于: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 年前的芯片设计,具有微秒精度或更差,需要数千个周期才能读取。
关于c - getrusage 返回四舍五入的数字,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19043873/