Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find CPU usage for a Thread in Linux

I have a C based application running on linux, with around 30 threads. Now I need to write a small utility which finds the CPU usage of each thread at given time. It can be a separate or part of the application.

One of the problem of /proc is finding which thread is what.

Please give me some ideas on how to start.

Thanks

like image 896
hari Avatar asked Feb 24 '12 12:02

hari


2 Answers

As notes by the OP, the /proc file system has a 'stat' file for each process, /proc/PROCESS-ID/stat and for each task /proc/PROCESS-ID/task/TASKID/stat. The later is the process stat is aggregate of all tasks (including completed tasks!).

As per man proc: fields 14, 15 in stat file include CPU (user, kernel) used.

That leave with the task of mapping threads to TASKID. As noted in the man page (see quotes), there is no direct API to gettid, instead the syscall is needed

For interactive utility, consider top (use y for task mode)

For code that can be used inside an app, see below

#define _GNU_SOURCE
#include <stdio.h>

#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>

pid_t get_task_id(void) ;
int get_task_cpu(pid_t tid) ;

int main(int argc, char *argv[])
{
    pthread_create(...) ;
}

void thread_proc(void *arg) {
    pid_t tid = get_task_id() ;

    // do something

    int cpu = get_task_cpu(tid) ;
    printf("TID=%d CPU=%d\n", tid, cpu) ;
}

pid_t get_task_id(void) {
    pid_t tid = syscall(SYS_gettid);
    return tid ;
}

int get_task_cpu(pid_t tid) {
    char fname[200] ;
    snprintf(fname, sizeof(fname), "/proc/self/task/%d/stat", (int) get_task_id()) ;
    FILE *fp = fopen(fname, "r") ;
    if ( !fp ) return -1 ;
    int ucpu = 0, scpu=0, tot_cpu = 0 ;
    if ( fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %d %d",
        &ucpu, &scpu) == 2 )
        tot_cpu = ucpu + scpu ;
    fclose(fp) ;
    return tot_cpu ;
}

The man page for gettid states:

GETTID(2)

NAME gettid - get thread identification

SYNOPSIS #include

   pid_t gettid(void);

   Note: There is no glibc wrapper for this system call; see NOTES.

And later on: NOTES Glibc does not provide a wrapper for this system call; call it using syscall(2).

   The thread ID returned by this call is not the same thing as a POSIX thread ID (i.e., the opaque value returned by pthread_self(3)).

With the example code in syscall

   #define _GNU_SOURCE
   #include <unistd.h>
   #include <sys/syscall.h>
   #include <sys/types.h>
   #include <signal.h>

   int
   main(int argc, char *argv[])
   {
       pid_t tid;

       tid = syscall(SYS_gettid);
       ...
    }
like image 62
dash-o Avatar answered Oct 08 '22 13:10

dash-o


I recommend to give every thread a human-readable name. This name is visible in thread-level "ps" output (so "ps -L PID").

You give each thread a name with this (non-portable) pthread api:

int pthread_setname_np(pthread_t thread, const char *name);

Example output for the multi-threaded thunderbird:

 % ps -o pid,pcpu,comm,cmd -L 7111
  PID %CPU COMMAND         CMD
 7111  8.3 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 Gecko_IOThread  /usr/lib/thunderbird/thunderbird
 7111  0.0 Link Monitor    /usr/lib/thunderbird/thunderbird
 7111  0.0 Socket Thread   /usr/lib/thunderbird/thunderbird
 7111  0.0 JS Watchdog     /usr/lib/thunderbird/thunderbird
 7111  0.0 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.1 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.1 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.1 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.0 AudioIPC Callba /usr/lib/thunderbird/thunderbird
 7111  0.0 AudioIPC Server /usr/lib/thunderbird/thunderbird
 7111  0.0 BGReadURLs      /usr/lib/thunderbird/thunderbird
 7111  0.0 Hang Monitor    /usr/lib/thunderbird/thunderbird
 7111  0.0 gmain           /usr/lib/thunderbird/thunderbird
 7111  0.0 gdbus           /usr/lib/thunderbird/thunderbird
 7111  0.0 Cache2 I/O      /usr/lib/thunderbird/thunderbird
 7111  0.0 Cookie          /usr/lib/thunderbird/thunderbird
 7111  0.0 Timer           /usr/lib/thunderbird/thunderbird
 7111  0.0 GMPThread       /usr/lib/thunderbird/thunderbird
 7111  0.5 Softwar~cThread /usr/lib/thunderbird/thunderbird
 7111  0.0 Compositor      /usr/lib/thunderbird/thunderbird
 7111  0.0 VRListener      /usr/lib/thunderbird/thunderbird
 7111  0.0 ImgDecoder #1   /usr/lib/thunderbird/thunderbird
 7111  0.0 ImageIO         /usr/lib/thunderbird/thunderbird
 7111  0.0 IPDL Background /usr/lib/thunderbird/thunderbird
 7111  0.0 HTML5 Parser    /usr/lib/thunderbird/thunderbird
 7111  0.0 LoadRoots       /usr/lib/thunderbird/thunderbird
 7111  0.0 DataStorage     /usr/lib/thunderbird/thunderbird
 7111  0.0 DataStorage     /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #1   /usr/lib/thunderbird/thunderbird
 7111  0.0 StyleThread#0   /usr/lib/thunderbird/thunderbird
 7111  0.0 StyleThread#1   /usr/lib/thunderbird/thunderbird
 7111  0.0 StyleThread#2   /usr/lib/thunderbird/thunderbird
 7111  0.0 ImgDecoder #2   /usr/lib/thunderbird/thunderbird
 7111  0.0 dconf worker    /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #2   /usr/lib/thunderbird/thunderbird
 7111  0.0 SysProxySetting /usr/lib/thunderbird/thunderbird
 7111  0.0 ProxyResolution /usr/lib/thunderbird/thunderbird
 7111  0.0 DataStorage     /usr/lib/thunderbird/thunderbird
 7111  0.0 URL Classifier  /usr/lib/thunderbird/thunderbird
 7111  0.0 Classif~ Update /usr/lib/thunderbird/thunderbird
 7111  0.0 DNS Resolver #1 /usr/lib/thunderbird/thunderbird
 7111  0.0 DOM Worker      /usr/lib/thunderbird/thunderbird
 7111  0.0 ImageBr~geChild /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #3   /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #4   /usr/lib/thunderbird/thunderbird
 7111  0.0 DNS Resolver #2 /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #5   /usr/lib/thunderbird/thunderbird
 7111  0.0 ImgDecoder #3   /usr/lib/thunderbird/thunderbird
 7111  0.0 DNS Resolver #3 /usr/lib/thunderbird/thunderbird
 7111  0.0 localStorage DB /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
like image 3
scottbiker Avatar answered Oct 08 '22 11:10

scottbiker