这是关于格特鲁萨吉。效果不错,但是精度/粒度不够精确。
它不依赖于 CPU 及其性能。仅取决于内核。对于实际内核 4+精度为3800μs(微秒)。对于内核 3.x,该时间为 10,000 μs
但是 macos 提供了更精确的 CPU 使用率。它大约是 14 μs(比 Linux 精确 270 倍)其次,在 FreeBSD 及其 Linux 兼容层上,getrusage 每次调用都会返回更新的 CPU 使用率值(例如精度为 1.9 微秒)
我可以使用 sysctl 或重新编译内核来调整精度吗?
[更新] 详细百分位数和直方图
278 increments a second, e.g. 3,597.1 microseconds in average
1%: 3.000 5%: 19.000 10%: 493.000 20%: 3,500.000 30%: 3,511.000
40%: 3,967.000 50%: 4,002.000 60%: 4,012.000 70%: 4,017.000 80%: 4,447.000
90%: 4,503.000 95%: 4,508.000 99%: 4,567.000
Histogram 'CPU Usage increments (microseconds)'
2.000 ... 399.417 9.7% | @@@@@@@@@@
399.417 ... 796.833 1.1% | @
796.833 ... 1,194.250 0.4% |
1,194.250 ... 1,591.667 |
1,591.667 ... 1,989.083 0.7% |
1,989.083 ... 2,386.500 0.4% |
2,386.500 ... 2,783.917 0.4% |
2,783.917 ... 3,181.333 0.7% |
3,181.333 ... 3,578.750 21.2% | @@@@@@@@@@@@@@@@@@@@@@@
3,578.750 ... 3,976.167 5.8% | @@@@@@
3,976.167 ... 4,373.583 38.5% | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
4,373.583 ... 4,771.000 21.2% | @@@@@@@@@@@@@@@@@@@@@@@
答案1
您能否提供参考文献和/或测试方法,以得出您在问题中发布的数字?
我可以观察到精确到微秒的粒度,但怀疑它是否真的精确到微秒。
我编写了一个简单的程序,列出用户和系统时间几次,然后仅当两者都改变几次时才列出:
/*****************************************************************************
*
* testrusage.c 2023.09.21 Smythies
* Attempt to observe rusage time granularity.
* see also: https://askubuntu.com/questions/1486310/how-to-tune-cpu-usage-granularity
*
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <sys/times.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <time.h>
unsigned long long stamp(void){
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC_RAW,&tv);
return (unsigned long long)tv.tv_sec * 1000000000 + tv.tv_nsec;
} /* endprocedure */
int main(){
unsigned long long start, now, last;
long tps;
long sys_call_counter = 0;
int i, j;
long old_sys, old_user, new_sys, new_user;
struct rusage usage;
start = stamp();
last = start;
for(i = 0; i < 5; i++){
getrusage(RUSAGE_SELF, &usage);
sys_call_counter++;
now = stamp();
printf("loops: %ld : ", sys_call_counter);
printf("Elapsed:%llu nS. ", now-start);
printf("Delta:%llu nS. : ru : ", now-last);
printf("user cpu: %ld uSec. ", usage.ru_utime.tv_usec);
printf("sys cpu: %ld uSec.\n", usage.ru_stime.tv_usec);
last = now;
} /* endfor */
printf("\n");
old_sys = usage.ru_stime.tv_usec;
old_user = usage.ru_utime.tv_usec;
i = 0;
while(i < 20){
getrusage(RUSAGE_SELF, &usage);
sys_call_counter++;
new_sys = usage.ru_stime.tv_usec;
new_user = usage.ru_utime.tv_usec;
if((old_sys != new_sys) && (old_user != new_user)){
for(j = 0; j < 1; j++){
now = stamp();
printf("loops: %ld : ", sys_call_counter);
printf("Elapsed:%llu nS. ", now-start);
printf("Delta:%llu nS. : ru : ", now-last);
printf("user old: %ld uSec. ", old_user);
printf("sys old: %ld uSec. ", old_sys);
printf("user cpu: %ld uSec. ", new_user);
printf("sys cpu: %ld uSec.\n", new_sys);
last = now;
getrusage(RUSAGE_SELF, &usage);
sys_call_counter++;
new_sys = (long) usage.ru_stime.tv_usec;
new_user = (long) usage.ru_utime.tv_usec;
} /* endfor */
old_sys = new_sys;
old_user = new_user;
i++;
} /* endif */
} /* endwhile */
} /* endprogram */
并得到这个:
doug@s19:~/c$ ./testrusage
loops: 1 : Elapsed:2569 nS. Delta:2569 nS. : ru : user cpu: 292 uSec. sys cpu: 0 uSec.
loops: 2 : Elapsed:37342 nS. Delta:34773 nS. : ru : user cpu: 327 uSec. sys cpu: 0 uSec.
loops: 3 : Elapsed:38697 nS. Delta:1355 nS. : ru : user cpu: 329 uSec. sys cpu: 0 uSec.
loops: 4 : Elapsed:39827 nS. Delta:1130 nS. : ru : user cpu: 330 uSec. sys cpu: 0 uSec.
loops: 5 : Elapsed:40824 nS. Delta:997 nS. : ru : user cpu: 331 uSec. sys cpu: 0 uSec.
loops: 904 : Elapsed:205213 nS. Delta:164389 nS. : ru : user old: 331 uSec. sys old: 0 uSec. user cpu: 491 uSec. sys cpu: 3 uSec.
loops: 6486 : Elapsed:1203157 nS. Delta:997944 nS. : ru : user old: 491 uSec. sys old: 6 uSec. user cpu: 493 uSec. sys cpu: 1000 uSec.
loops: 9316 : Elapsed:1711772 nS. Delta:508615 nS. : ru : user old: 495 uSec. sys old: 1000 uSec. user cpu: 1001 uSec. sys cpu: 1001 uSec.
loops: 9319 : Elapsed:1713784 nS. Delta:2012 nS. : ru : user old: 1001 uSec. sys old: 1001 uSec. user cpu: 1002 uSec. sys cpu: 1002 uSec.
loops: 9322 : Elapsed:1715740 nS. Delta:1956 nS. : ru : user old: 1002 uSec. sys old: 1002 uSec. user cpu: 1003 uSec. sys cpu: 1003 uSec.
loops: 9325 : Elapsed:1717655 nS. Delta:1915 nS. : ru : user old: 1003 uSec. sys old: 1003 uSec. user cpu: 1004 uSec. sys cpu: 1004 uSec.
loops: 9328 : Elapsed:1719611 nS. Delta:1956 nS. : ru : user old: 1004 uSec. sys old: 1004 uSec. user cpu: 1005 uSec. sys cpu: 1005 uSec.
loops: 9332 : Elapsed:1721729 nS. Delta:2118 nS. : ru : user old: 1005 uSec. sys old: 1005 uSec. user cpu: 1006 uSec. sys cpu: 1006 uSec.
loops: 9335 : Elapsed:1723650 nS. Delta:1921 nS. : ru : user old: 1006 uSec. sys old: 1006 uSec. user cpu: 1007 uSec. sys cpu: 1007 uSec.
loops: 9339 : Elapsed:1725728 nS. Delta:2078 nS. : ru : user old: 1007 uSec. sys old: 1007 uSec. user cpu: 1008 uSec. sys cpu: 1008 uSec.
loops: 9342 : Elapsed:1727697 nS. Delta:1969 nS. : ru : user old: 1008 uSec. sys old: 1008 uSec. user cpu: 1009 uSec. sys cpu: 1009 uSec.
loops: 9346 : Elapsed:1729758 nS. Delta:2061 nS. : ru : user old: 1009 uSec. sys old: 1009 uSec. user cpu: 1010 uSec. sys cpu: 1010 uSec.
loops: 9349 : Elapsed:1731665 nS. Delta:1907 nS. : ru : user old: 1010 uSec. sys old: 1010 uSec. user cpu: 1011 uSec. sys cpu: 1011 uSec.
loops: 9352 : Elapsed:1733646 nS. Delta:1981 nS. : ru : user old: 1011 uSec. sys old: 1011 uSec. user cpu: 1012 uSec. sys cpu: 1012 uSec.
loops: 9356 : Elapsed:1735733 nS. Delta:2087 nS. : ru : user old: 1012 uSec. sys old: 1012 uSec. user cpu: 1013 uSec. sys cpu: 1013 uSec.
loops: 9359 : Elapsed:1737668 nS. Delta:1935 nS. : ru : user old: 1013 uSec. sys old: 1013 uSec. user cpu: 1014 uSec. sys cpu: 1014 uSec.
loops: 9362 : Elapsed:1739614 nS. Delta:1946 nS. : ru : user old: 1014 uSec. sys old: 1014 uSec. user cpu: 1015 uSec. sys cpu: 1015 uSec.
loops: 9366 : Elapsed:1741727 nS. Delta:2113 nS. : ru : user old: 1015 uSec. sys old: 1015 uSec. user cpu: 1016 uSec. sys cpu: 1016 uSec.
loops: 9369 : Elapsed:1743624 nS. Delta:1897 nS. : ru : user old: 1016 uSec. sys old: 1016 uSec. user cpu: 1017 uSec. sys cpu: 1017 uSec.
loops: 9372 : Elapsed:1745647 nS. Delta:2023 nS. : ru : user old: 1017 uSec. sys old: 1017 uSec. user cpu: 1018 uSec. sys cpu: 1018 uSec.
注 1:我没有旧版 4 系列或 3 系列内核。我是在 6.X 系列内核上执行此操作的。(我可以在 5.15 系列内核上执行此操作,但我没有这样做。)
注 2:我正在使用支持高分辨率计时器的硬件和内核:
doug@s19:~/c$ grep CONFIG_HIGH_RES_TIMERS /boot/con*
...
/boot/config-5.15.0-79-generic:CONFIG_HIGH_RES_TIMERS=y
/boot/config-5.15.0-83-generic:CONFIG_HIGH_RES_TIMERS=y
...
/boot/config-5.4.0-162-generic:CONFIG_HIGH_RES_TIMERS=y
...
/boot/config-6.6.0-rc2-stock:CONFIG_HIGH_RES_TIMERS=y
这些计时器可以测量到 uSec:
doug@s19:~/tmp$ sudo cat /proc/timer_list | grep min_delta_ns
min_delta_ns: 8001
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
min_delta_ns: 1000
编辑:我修改了我的程序,以便只打印一些总数,并运行 getrusage 报告的 1 亿次用户或系统时间更改。
耗时为 100.004 秒,即每次更改平均耗时 1 微秒。
对 getrusage 的调用次数为 5.299 亿次。
总用户时间和系统时间为 14320833 微秒和 85683415 微秒,与top
执行期间报告的结果非常吻合。