2

From the bash time command on different stock Ubuntu systems (both real hardware and VMs) all with CONFIG_HZ=250, I'm sometimes getting real 0m0.001s, user 0m0.001s or sys 0m0.001s as well as any other number of milliseconds.

How is this possible ?

Edit: I admit the elapsed (real) time can be computed exactly by querying any of the available high resolution time sources at the beginning and the end of the time command.
But because there is no time source query on system call entry or exit for performance reasons I expected the accounting of user and sys CPU times to be in timer ticks (number of timer interrupts) which would be multiples of 4 ms.

2nd edit: Taking MC68020's answer into account, the question becomes: How is the Linux kernel able to return user and sys CPU usages with microsecond accuracy from the getrusage syscall ?
Did I do wrong when arguing there cannot be a time source query on each system call entry and exit for performance reasons ?

2 Answers 2

1

As you can read from some code

#if defined (HAVE_GETRUSAGE) && defined (HAVE_TIMEVAL) && defined (RUSAGE_SELF)
...
  getrusage (RUSAGE_SELF, &self);
...
  print_timeval (stdout, &self.ru_utime);
...
#else
#  if defined (HAVE_TIMES)
...
  times (&t);
  print_clock_t (stdout, t.tms_utime);
...

Depending on HAVE_GETRUSAGE, HAVE_TIMEVAL and RUSAGE_SELF settings, bash's time internal command will either use the getrusage system call or the times system call.

In case getrusage is used, then bash's time command will use the ru_stime and ru_utime members of the rusage structure and compute the members of their associated timeval structure with, according to the manual page linked herabove, a microsecond accuracy.

In case the times system call is used then bash's time command will output the members of the associated clock_t structure. In this precise case, values are indeed reported in clock ticks and you are therefore correct writing that the precision of the values reported just cannot be better than 1/CONFIG_HZ.

As you might read in the times system call manual page, its use is discouraged for many reasons. So I believe the settings in your system (HAVE_GETRUSAGE…) are appropriate to enable bash not to have to resort to it. If not then… you are correct, the precision you report is just… absurd.


A/ Why getrusage can report timings with a better precision than 1/CONFIG_HZ : Because :

Since Linux 2.6.21, Linux supports high-resolution timers (HRTs), On a system that supports HRTs, the accuracy of sleep and timer system calls is no longer constrained by the jiffy, but instead can be as accurate as the hardware allows (microsecond accuracy is typical of modern hardware).

As you can read in this overview of time and timers.


B/ How can whatever sort of accuracy regarding utime/stime be achieved if no timer is set right at the beginning of each system call and read right after it completes :

Precise cputime : Who cares ? The scheduler! The scheduler in its Completely Fair sharing attributions not to forget its obligations to take care of tasks willing to… nanosleep…
What cputime ? : Grand total of course ! That is to say u_time + s_time since (apart from some very rare exceptions) the scheduler does not care a damn how (in which context) tasks squander their time slices.
So who cares for the s/u time ratios ? : cpu accounting afficionados!

B.1/ So… distinguishing u_time and s_time ?… let's… assume!

In the (good ?) old times of Linux (understand < about 2.6.? kernels) cpu accounting was some sort of simple(istic?) heuristic : When some task is scheduled out, the scheduler takes note of the context in which the task was running and… :

cpu accounting will just be happy assuming that : all the time the task has been running since it was scheduled in was spent in the context it was running when scheduled out !

From that, one can understand that debating on the accuracy of the user and system cpu time separate reports because of whatever clock precision is somehow meaningless : There is just an error in the determination of what is what. An error that will just be cumulated over time. Only chance, added with a good number of times the task went scheduled in/out in its lifetime can help the cpu time accounting afficionado expecting that errors in + will compensate errors in - and therefore whatever meaningfulness of these values (as taken separately since their sum remains indeed and accurate and meaningful)

B.2/ Error OK but… not THAT much ! So… let's go… virtual!

On systems with virtual CPUs, when using more virtual CPUs than real CPUs on the virtual platform, the real CPUs might spend part of their time servicing another virtual processor while the time slice might be accounted to some process which actually could not utilize it.
This leading to not only erroneous but completely unrealistic s_time figures.

Long story made short, around about 2.6.? kernels, linux came with the Virtual CPU time accounting feature providing, among many other things, CPU times accounting, whenever the execution context changes and consequently enabling definitely and precise and accurate u-times and s-times.

As anywhere, there is no free lunch… (per cpu) timers everywhere… expect some significant overhead.

Nevermind, many top rated distro (RHEL, SUZE…) quickly made this virtual cpu time accounting default.

Nevermind (me personally) thanks to some kernel tunable ( CONFIG_TICK_CPU_ACCOUNTING ) offered since 3.7, (and AFAIK still default on stock Linux versions) I can still opt for the (good ?) old cheep cpu accounting method since… I (personally) only care about the summ u_time + s_time.

That'll be all folks ;-)

3
  • Thank you for this analysis pointing to the getrusage syscall. With that being said, the question is still open because it is still not clear how microsesond precision on the user and sys CPU usages is possible with only a four millisecond timer interrupt. I edited the question a second time.
    – Juergen
    Commented Oct 14, 2022 at 13:45
  • @Juergen : Your question can now be split into two items : how comes getrusage can provide microsecond precision and how comes precise timings of system calls can be achieved without setting/reading a timer on boundaries of system calls. I updated my answer for the former, I'll do my best to answer the latter… in some (expected near ;-) ) future.
    – MC68020
    Commented Oct 14, 2022 at 16:23
  • 1
    Marking the answer as correct: The edited info explains the varying results when repeating the same short shell script on an otherwise idle system with buffer cache access only (no I/O).
    – Juergen
    Commented Nov 11, 2022 at 9:57
0

The time tool is not required to use the times() function, isn't it? The times() is looking at the CONFIG_HZ yes. But it is not an only function working with time.

For example, function clock_gettime() goes to a hardware clock and ignores the CONFIG_HZ. And the granularity of clock_gettime() is limited only by the hardware. The better your CPU - the more precise the clock_gettime() is.

1
  • This explains how the elapsed time can be computed more precisely than the timer interrupt but it does not explain how the system and user times can be accounted for in higher precision.
    – Juergen
    Commented Oct 13, 2022 at 8:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .