Julia Evans

How to measure your CPU time: clock_gettime!

I’m super into measuring CPU time. If you have a slow program, the first thing you want to know is whether your program is spending that time calculating things on the CPU, or whether it’s waiting for something else (a disk, a network, user input).

At work yesterday, someone sent an email saying “Hey we’re measuring how much CPU time every HTTP request takes now!”. I didn’t know how to accomplish what they said they’d just done. So I asked “hey how does that work?”. Here’s the answer.

It turns out that if you’re a HTTP server, and you want to know exactly how much CPU time your HTTP requests are taking, you can just ask the Linux kernel!

On Linux, there’s a system call (and corresponding libc function) called clock_gettime. I’d seen this system call before, but I thought it was only for getting the time, like 5:03pm. Not so! Here are the flags you can send to clock_gettime on my system. (from man clock_gettime).

       CLOCK_REALTIME
              System-wide  real-time  clock.    Setting   this   clock
              requires appropriate privileges.

       CLOCK_MONOTONIC
              Clock  that  cannot be set and represents monotonic time
              since some unspecified starting point.

       CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
              Similar to CLOCK_MONOTONIC, but provides access to a raw
              hardware-based  time  that is not subject to NTP adjust‐
              ments.

       CLOCK_PROCESS_CPUTIME_ID
              High-resolution per-process timer from the CPU.

       CLOCK_THREAD_CPUTIME_ID
              Thread-specific CPU-time clock.

So if you ask your kernel for CLOCK_PROCESS_CPUTIME_ID, it will tell you how much CPU time has passed since your program started. This is awesome, because you can run

start_time = clock_gettime(CLOCK_PROCESS_CPUTIME_ID)
do_maybe_expensive_thing
end_time = clock_gettime(CLOCK_PROCESS_CPUTIME_ID)
print "elapsed CPU time:", end_time - start_time

And you can call clock_gettime from Ruby to understand your Ruby performance!. System calls aren’t just for C hackers, they’re for everyone.

In hindsight, it makes sense to me that Linux keeps track of the CPU time spent per process. ps aux reports how much CPU time every program on your system has used (in the TIME column), and if you time a program with time, it reports the total time, userspace CPU time, and kernel CPU time separately.

It’s also interesting that this system call lets you get a monotonic time – that seems useful if you want a notion of time that doesn’t go back in time.