From f80b1acf732acd16e4b8894b6d5eab970b9822ce Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Fri, 20 Jun 2025 17:05:51 +0200 Subject: [PATCH] Update readme with explanations of examples --- README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/README.md b/README.md index a545302..4c1a0a4 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,76 @@ specific thread. The OpenJDK garbage collector implementations as well as other parts of the OpenJDK needs this information. Since I had written it, I figured I might as well share it with the community. Perhaps some will find it useful. +The code demonstrated three ways of getting the run time of a thread other than +the requesting thread, and one way of getting the run time of the current +thread. + +## Getting run time via `clock_gettime(2)` + +The system function `clock_gettime(2)` will return a `struct timespec` +representing the current time of a given clock. We can obtain a clock that +holds the total run time of a thread by calling `pthread_getcpuclockid(3)`. + +This is the sum of the user and sys time of the given thread with nanosecond +precision. + +See [fast_cpu_time.cpp](./fast_cpu_time.cpp) for an example of using this method. + +## Getting run time via `libprocstat(3)` + +Using the functions provided by `libprocstat(3)` we can obtain the separate +user and sys times for a thread with microsecond precision. This involves first +opening a procstat handle (`struct procstat *`) using +`procstat_open_sysctl(3)`, querying the process info for all threads in the +process using `procstat_getprocs(3)`, and the and iterating through the +returned array to find requested thread. + +The call to `procstat_getprocs(3)` will dynamically allocate the memory for the +returned array, which then has to be freed using `procstat_freeprocs(3)` after +use. Finally the procstat handle must be freed using `procstat_close(3)`. + +In addition this method requires that we link with `libprocstat(3)`. + +The returned data is an array of `struct kinfo_proc` structures, that contains +a field of type `struct rusage`, which again contains a `struct timeval` for +the threads user time and one for the system time. These have microsecond +precision. + +To locate the requested thread we need the _kernel thread id_ of the thread. +We can obtain this by calling `pthread_getthreadid_np(3)`, but only from +the thread itself. To be able to use it from another thread, the thread id +must be saved somewhere accessible. In this example I just use a global +variable for illustration. + +See [procstat_cpu_time.cpp](./procstat_cpu_time.cpp) for an example using this +method. + +## Getting run time via `sysctl(3)` + +This is very similar to the libprocstat method above, but don't require linking +with a library, and uses memory allocated by the caller rather than allocating +it dynaically for you. This allows for using static preallocated memory if +needed. + +While the `KERN_PROC_INC_THREAD` modifier flag for `KERN_PROC_PID` is not +documented in the `sysctl(3)` man page, it works the same as for the procstat +call. + +See [syscall_cpu_time.cpp](./syscall_cpu_time.cpp) for an example of using this +method. + +## Getting run time vis `getrusage(2)` + +This method is pretty straight forward, but will only get the run time for the +calling thread. It has the same microsecond precision that both the libprocstat +and sysctl methods above has. + +It also avoids the need for dynamic allocation as the caller provides a buffer +of type `struct rusage` that is filled with the data. + +See the code for the thread itself in [main.cpp](./main.cpp) for an example of +using this method. + ## License ```