[Linux] [C] Get CPU time per process / thread

I had a chance to look it up, so I summarized it in a little more detail.

Get CPU time for process

clock_gettime (CLOCK_PROCESS_CPUTIME_ID)

Example of use


struct timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts)

getrusage (RUSAGE_SELF) Returns the resource usage of the calling process, the sum of the resources used by all threads in that process.

Example of use


struct rusage usg;
getrusage(RUSAGE_THREAD, &usg);

Get CPU time for threads

clock_gettime (CLOCK_THREAD_CPUTIME_ID)

Example of use


struct timespec ts;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts)

In the case of the above acquisition, only its own CPU time can be acquired in each thread. If you want to earn money from outside the thread, get it in combination with the following pthread_getcpuclockid.

pthread_getcpuclockid + clock_gettime

Example of use


//Thread creation
pthread_t thread;
pthread_create(&thread, NULL, thread_start, NULL);

clockid_t cid;
pthread_getcpuclockid(pthread_self(), &cid); //To get the clockid of the main thread
pthread_getcpuclockid(thread, &cid); //To get the clockid of a specific thread

struct timespec ts;
clock_gettime(cid, &ts)

getrusage (RUSAGE_THREAD) Returns resource usage statistics for the calling thread

Example of use


struct rusage usg;
getrusage(RUSAGE_THREAD, &usg);

Example of use

This is an implementation example. This is a slightly modified version of the Man Page sample code below. Man page of PTHREAD_GETCPUCLOCKID I wanted to use atomic variables (stdatomic.h), so I need to build with C11.

Implementation example


// to use RUSAGE_THREAD
#define _GNU_SOURCE
#include <sys/resource.h>

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>

// C11 only
#include <stdatomic.h>

#define handle_error(msg) \
        do { perror(msg); exit(EXIT_FAILURE); } while (0)

#define handle_error_en(en, msg) \
        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

_Atomic int thread_end_flag = ATOMIC_VAR_INIT(0);

static void
pclock(char *msg, clockid_t cid)
{
    struct timespec ts;

    printf("%s", msg);
    if (clock_gettime(cid, &ts) == -1)
        handle_error("clock_gettime");
    printf("%4ld.%03ld\n", ts.tv_sec, ts.tv_nsec / 1000000);
}

static void *
thread_start(void *arg)
{
    printf("Subthread starting infinite loop\n");

    for (;;)
    {
        if (thread_end_flag) break;
        continue;
    }

    pclock("SubThread CPU time: ", CLOCK_PROCESS_CPUTIME_ID);
    // rusage
    int s;
    struct rusage usg;
    s = getrusage(RUSAGE_THREAD, &usg);
    if (s != 0)
        handle_error_en(s, "getrusage(thread)");
    printf("getrusage(thread) : user ");
    printf("%4ld.%03ld, ", usg.ru_utime.tv_sec, usg.ru_utime.tv_usec / 1000);
    printf("system ");
    printf("%4ld.%03ld\n", usg.ru_stime.tv_sec, usg.ru_stime.tv_usec / 1000);
}

int
main(int argc, char *argv[])
{
    pthread_t thread;
    clockid_t cid;
    int j, s;

    s = pthread_create(&thread, NULL, thread_start, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_create");

    printf("Main thread sleeping\n");
    sleep(1);

    printf("Main thread consuming some CPU time...\n");
    for (j = 0; j < 2000000; j++)
        getppid();

    pclock("Process total CPU time: ", CLOCK_PROCESS_CPUTIME_ID);

    s = pthread_getcpuclockid(pthread_self(), &cid);
    if (s != 0)
        handle_error_en(s, "pthread_getcpuclockid");
    pclock("Main thread CPU time:   ", cid);

    /* The preceding 4 lines of code could have been replaced by:
       pclock("Main thread CPU time:   ", CLOCK_THREAD_CPUTIME_ID); */

    s = pthread_getcpuclockid(thread, &cid);
    if (s != 0)
        handle_error_en(s, "pthread_getcpuclockid");
    pclock("Subthread CPU time: 1    ", cid);

    // rusage
    struct rusage usg;
    s = getrusage(RUSAGE_SELF, &usg);
    if (s != 0)
        handle_error_en(s, "getrusage(process)");
    printf("getrusage(process) : user ");
    printf("%4ld.%03ld, ", usg.ru_utime.tv_sec, usg.ru_utime.tv_usec / 1000);
    printf("system ");
    printf("%4ld.%03ld\n", usg.ru_stime.tv_sec, usg.ru_stime.tv_usec / 1000);

    thread_end_flag = 1;
    pthread_join(thread, NULL);
}

Run


koara@ubuntu:~/work$ gcc -pthread -std=c11 test.c 
koara@ubuntu:~/work$ ./a.out 
Main thread sleeping
Subthread starting infinite loop
Main thread consuming some CPU time...
Process total CPU time:    1.143
Main thread CPU time:      0.078
Subthread CPU time: 1       1.064
getrusage(process) : user    1.076, system    0.064
SubThread CPU time:    1.143
getrusage(thread) : user    1.060, system    0.004

reference

Man page of CLOCK_GETRES Man page of PTHREAD_GETCPUCLOCKID Man page of GETRUSAGE Atomic-Introduction to C Atomic copy between atomic variables --yohhoy's diary

Recommended Posts

[Linux] [C] Get CPU time per process / thread
Get own process name at runtime in C / C ++ (for Linux)
[OS / Linux] Process, thread, memory management
[Linux] [C / C ++] Get tid (thread id) / Wrap pthread_create to get tid of child thread
Linux process
[C language] [Linux] Get the value of environment variable
Library for measuring execution time in Linux C applications