Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between getrusage(RUSAGE_THREAD, ...) and clock_gettime(CLOCK_THREAD_CPUTIME_ID,...) in Linux?

The question pretty much says it all. According to the man page for getrusage(), it returns:

           struct timeval ru_utime; /* user CPU time used */
           struct timeval ru_stime; /* system CPU time used */

According to the man page for clock_gettime(), it returns:

   CLOCK_THREAD_CPUTIME_ID (since Linux 2.6.12)
          Thread-specific CPU-time clock.

So, how does (thread specific) "user/system CPU time used" differ from a thread-specific CPU-time clock?

Obviously, I'm asking because I see a difference between the two in an application I have ported to Linux (from a custom RTOS). That application has an internal profiling capability implemented with tick() and tock() functions. As I have been digging into this, I have degenerated one part of my application to be:

tick()
// code commented out
tock()

The tick() function records the time at which it was run, the tock() function records the time at which it was run, computes the delta between the two, and reports that delta. When I implement tick() and tock() using getrusage(), I get mostly 0's out, and occasionally 1000us or 10000us values (according to whether I have configured my kernel for 1kHz or 100Hz operation). When I implement tick() & tock() using clock_gettime(), I get values centered about 13us (with bizarre excursions to 75us or 100us occasionally, but I'll deal with later).

I have tried enabling high res timers in the kernel and various combinations of VIRT_CPU_ACCOUNTING and/or VIRT_CPU_ACCOUNTING_GEN. The only effect I have seen is that the non-zero values reported by getrusage() change from 1000us to a range of higher precision values centered about 1000us.

I finally switched to using clock_gettime() and have much more believable results, but I am left wondering why the two system calls exist, and why they behave so differently. So I figured I should ask some experts.

like image 811
Patrick Doyle Avatar asked Oct 31 '22 12:10

Patrick Doyle


1 Answers

What is the difference between getrusage(RUSAGE_THREAD, …) and clock_gettime(CLOCK_THREAD_CPUTIME_ID,…) in Linux?

clock_gettime(CLOCK_THREAD_CPUTIME_ID, …) ultimately calls task_sched_runtime(p), which takes the accounted runtime from p->se.sum_exec_runtime, where struct task_struct *p is current.

getrusage(RUSAGE_THREAD, …) calls task_cputime_adjusted(current, &utime, &stime), for which two definitions [a], [b] exist; which of them is used depends on the Linux kernel configuration item CONFIG_VIRT_CPU_ACCOUNTING_NATIVE:

Select this option to enable more accurate task and CPU time accounting.

Now we would need to know whether this option is selected in your kernel. Anyway, both cases look different from the method used by clock_gettime().

That said, I can't reproduce your findings (I get nearly the same numbers from both system calls). An example program could help further.

So I figured I should ask some experts.

I think you'd find the real experts on a Linux kernel mailing list.

like image 184
Armali Avatar answered Nov 02 '22 11:11

Armali