getrusage vs /proc/pid/stat?

getrusage vs /proc/pid/stat?

Post by Dan Kege » Tue, 19 Jun 2001 14:30:10



I'd like to monitor CPU, memory, and I/O utilization in a
long-running multithreaded daemon under kernels 2.2, 2.4,
and possibly also Solaris (#ifdefs are ok).

getrusage() looked promising, and might even work for CPU utilization.
Dunno if it returns info for all child threads yet, haven't tried it.
In Linux, though, getrusage() doesn't return any info about RAM.

I know I can get the RSS and VSIZE under Linux by parsing /proc/pid/stat,
but was hoping for a faster interface (although I suppose a seek,
a read, and an ascii parse isn't *that* slow).  Is /proc/pid/stat
the only way to go under Linux to monitor RSS?
- Dan

--
"A computer is a state machine.
 Threads are for people who can't program state machines."
         - Alan Cox
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

getrusage vs /proc/pid/stat?

Post by Pete Wyckof » Wed, 20 Jun 2001 03:00:09



Quote:> I'd like to monitor CPU, memory, and I/O utilization in a
> long-running multithreaded daemon under kernels 2.2, 2.4,
> and possibly also Solaris (#ifdefs are ok).

> getrusage() looked promising, and might even work for CPU utilization.
> Dunno if it returns info for all child threads yet, haven't tried it.
> In Linux, though, getrusage() doesn't return any info about RAM.

> I know I can get the RSS and VSIZE under Linux by parsing /proc/pid/stat,
> but was hoping for a faster interface (although I suppose a seek,
> a read, and an ascii parse isn't *that* slow).  Is /proc/pid/stat
> the only way to go under Linux to monitor RSS?

getrusage() isn't really the system call you want for this.

There is a max RSS value, which linux could support but doesn't, but
you seem to want to see the current RSS over time.  Search the archive
for various patches/complaints about getrusage.

For vsize, most OSes offer time-integral averages of text, data, and
stack sizes via getrusage().  Again, more of an aggregate than a current
snapshot, and again, linux returns zero for these currently.

                -- Pete
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

getrusage vs /proc/pid/stat?

Post by Dan Kege » Wed, 20 Jun 2001 06:30:11




> > I'd like to monitor CPU, memory, and I/O utilization in a
> > long-running multithreaded daemon under kernels 2.2, 2.4,
> > and possibly also Solaris (#ifdefs are ok).

> getrusage() isn't really the system call you want for this.

I'll buy that.  Looks like a lot of unices don't implement that
call fully, and Linux is one of them.

What is the proper way to measure total CPU time used by a multithreaded program?
The only way I can figure to do it is to sum /proc/pid/stat across
the threads of interest (see below).  Is this the easiest way,
or am I missing something?  (Forgive the C++.  I'd recode this in C
if it were for general use.)

========= LinuxTimes.h ==========
#include <sys/times.h>
#include <pthread.h>

/*--------------------------------------------------------------------------
 Source and test case at http://www.kegel.com/lt.tar.gz

 Monitor the CPU usage of a bunch of threads in the same process.
 This is a simulation of the system call times()
 providing traditional semantics under LinuxThreads.
 On e.g. Solaris, you don't need this; you just call the standard times().
--------------------------------------------------------------------------*/
class LinuxTimes {
    const static int MAXTHREADS = 100;

    /// number of threads being monitored
    int m_nthreads;

    /// fd open to /proc/pid/stat for each thread
    int m_proc_pid_stat_fd[MAXTHREADS];

    /// make addSelf threadsafe
    pthread_mutex_t m_lock;

public:

    LinuxTimes() { m_nthreads = 0; pthread_mutex_init(&m_lock, NULL); }

    /**
     New threads call this to add themselves to the group.
     Threadsafe.

     */
    int addSelf();

    /**
     Calculate user and system time accumulated by all threads in group.
     Return result in tms_utime and tms_stime fields of given struct tms.
     Similar to 'man 2 times' on Solaris (where all CPU time of all threads
     is counted as CPU time towards the process).

     */
    int times(struct tms *buf);

Quote:};

========= LinuxTimes.cc ==========

#include "LinuxTimes.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>      

/**
 New threads call this to add themselves to the group.
 Threadsafe.

 */
int LinuxTimes::addSelf()
{
    int fd;
    char fname[256];
    int err = 0;

    if (pthread_mutex_lock(&m_lock))
        return EINVAL;

    if (m_nthreads >= MAXTHREADS) {
        err = E2BIG;
    } else {
        // Under LinuxThreads, each thread has its own pid
        sprintf(fname, "/proc/%d/stat", getpid());
        fd = open(fname, O_RDONLY);
        if (fd == -1)
            err = errno;
        else {
            m_proc_pid_stat_fd[m_nthreads++] = fd;
        }
    }

    if (pthread_mutex_unlock(&m_lock))
        return EINVAL;

    return err;

Quote:}

/* Skip to char after nth whitespace.  Returns NULL on failure. */
static const char *skipNspace(const char *p, int n)
{
    while (*++p)
        if (isspace(*p) && ! --n)
            return p+1;
    return NULL;

Quote:}

/**
 Calculate user and system time accumulated by all threads in group.
 Return result in tms_utime and tms_stime fields of given struct tms.
 Similar to 'man 2 times' on Solaris (where all CPU time of all threads
 is counted as CPU time towards the process).

 */
int LinuxTimes::times(struct tms *buf)
{
    int i;
    int nread;

    buf->tms_utime = 0;
    buf->tms_stime = 0;
    for (i=0; i<m_nthreads; i++) {
        char scratch[1024]; // FIXME: is that big enough?
        int fd = m_proc_pid_stat_fd[i];

        // rewind to start of stat file.  (Not all /proc entries support this.)
        if (lseek(fd, 0, SEEK_SET))
            return EBADF;

        // Read in ASCII data and parse out utime and stime fields
        // (see 'man proc')
        nread = read(fd, scratch, sizeof(scratch)-1);
        if (nread < 50)     // FIXME: cheesy
            return EINVAL;
        scratch[nread] = 0;

        // Skip to end of command field
        // FIXME: what if executable has ) in its filename?  Bleh.
        const char *p = strchr(scratch, ')') + 2;

        // Skip to utime field
        p = skipNspace(p, 11);
        if (!p) return EINVAL;
        buf->tms_utime += atoi(p);

        // Skip to stime field
        p = skipNspace(p, 1);
        if (!p) return EINVAL;
        buf->tms_stime += atoi(p);
    }

    return 0;

Quote:}

==============

Thanks,
Dan

--
"A computer is a state machine.
 Threads are for people who can't program state machines."
         - Alan Cox
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

getrusage vs /proc/pid/stat?

Post by J . A . Magallo » Wed, 20 Jun 2001 14:10:07





>> > I'd like to monitor CPU, memory, and I/O utilization in a
>> > long-running multithreaded daemon under kernels 2.2, 2.4,
>> > and possibly also Solaris (#ifdefs are ok).

>> getrusage() isn't really the system call you want for this.

>I'll buy that.  Looks like a lot of unices don't implement that
>call fully, and Linux is one of them.

>What is the proper way to measure total CPU time used by a multithreaded program?

I have just the same problem. getrusage() did not catch the CPU time for
children, even if the man page said that. Now I am using times(2), that
seems to work in Solaris, but gives nothing in Linux.

I you look at time(1) manpage, it says time is implemented over the times(2)
system call. But if I include that call, it gives me only zero.

This is the output on Solaris:


Rendering box.jpg: 64x64
****************************************************************
Wall Time:0000:00:00.241
User Time:0000:00:00.600
Sys  Time:0000:00:00.000

real    0m0.59s
user    0m0.76s
sys     0m0.07s

(user is greater, cause it uses 4 cpus and times is cumulative)

And this is the output on Linux (2.4.5-ac15, glibc2.2.3)


Rendering box.jpg: 64x64
****************************************************************
Wall Time:0000:00:01.299
User Time:0000:00:00.000
Sys  Time:0000:00:00.000
real 1.43
user 2.63
sys 0.02

????? time gives good results for summed CPU time, but my own call
to times(2) fails ???

If they can help you (and if you see any error) here is my Timer:

timer.h:

#ifndef AST_TIMER_H
#define AST_TIMER_H

#include <ast/api.h>

class __apit Timer
{
protected:
        double  wstart,wlast,wnow;
        double  ustart,ulast,unow;
        double  sstart,slast,snow;
public:
static char*    format(double t);
        Timer();

        void reset();
        void update();

        double wall();
        double user();
        double system();

        double ewall();
        double euser();
        double esystem();

Quote:};

#endif // AST_TIMER_H

timer.cc:

#include <ast/timer.h>
#include <ast/stream.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#ifdef __UNX__
#include <sys/time.h>
#include <sys/times.h>
#include <sys/resource.h>
#include <unistd.h>
#endif

//#define USE_GETRUSAGE

char *Timer::format(double t)
{
        int     h  = int(t/3600);
        int     m  = int((t-h*3600)/60);
        int     s  = int(t-h*3600-m*60);
        int     ms = int(1000*(t-h*3600-m*60-s));

        char* str = new char[64];
        ostrstream ss(str,64,ios::trunc);
        ss << setfill('0');
        ss << setw(4) << h;
        ss << ":" << setw(2) << m;
        ss << ":" << setw(2) << s;
        ss << "." << setw(3) << ms;
        ss << ends;

        return str;

Quote:}

Timer::Timer()
{
        reset();

Quote:}

void Timer::reset()
{
        update();

        wstart = wnow;
        ustart = unow;
        sstart = snow;

Quote:}

void Timer::update()
{
// Wall clock time
#ifdef __UNX__
        struct timeval tv;

        gettimeofday(&tv,NULL);
        wnow = 1000*tv.tv_sec+1e-3*tv.tv_usec;
#endif
#ifdef __WIN__
        wnow = ::time(NULL)*1000;
#endif
#ifdef __MAC__
        wnow = ::time(NULL)*1000;
#endif

// CPU User and System times
#ifdef __UNX__
#ifdef USE_GETRUSAGE
        struct rusage rus,ruc;
        getrusage(RUSAGE_SELF,&rus);
        getrusage(RUSAGE_CHILDREN,&ruc);

        double s,u;

        s = rus.ru_utime.tv_sec+ruc.ru_utime.tv_sec;
        u = rus.ru_utime.tv_usec+ruc.ru_utime.tv_usec;
        unow = 1000*s+1e-3*u;

        s = rus.ru_stime.tv_sec+ruc.ru_stime.tv_sec;
        u = rus.ru_stime.tv_usec+ruc.ru_stime.tv_usec;
        snow = 1000*s+1e-3*u;
#else
        struct tms t;
        times(&t);

        double s;

        s = t.tms_utime+t.tms_cutime;
#ifdef __linux__
        unow = double(1000*s)/double(sysconf(_SC_CLK_TCK));
#else
        unow = double(1000*s)/double(CLK_TCK);
#endif

        s = t.tms_stime+t.tms_cstime;
#ifdef __linux__
        snow = double(1000*s)/double(sysconf(_SC_CLK_TCK));
#else
        snow = double(1000*s)/double(CLK_TCK);
#endif

#endif
#endif
#ifdef __WIN__
        unow = ::time(NULL)*1000;
        snow = 0;
#endif
#ifdef __MAC__
        unow = ::time(NULL)*1000;
        snow = 0;
#endif

        wlast = wnow;
        ulast = unow;
        slast = snow;

Quote:}

double Timer::wall()
{
        update();
        return 0.001*(wnow-wstart);

Quote:}

double Timer::user()
{
        update();
        return 0.001*(unow-ustart);

Quote:}

double Timer::system()
{
        update();
        return 0.001*(snow-sstart);

Quote:}

double Timer::ewall()
{
        double last = wlast;
        update();
        return 0.001*(wnow-last);

Quote:}

double Timer::euser()
{
        double last = ulast;
        update();
        return 0.001*(unow-last);

Quote:}

double Timer::esystem()
{
        double last = slast;
        update();
        return 0.001*(snow-last);

Quote:}

--
J.A. Magallon                           #  Let the source be with you...        

Linux Mandrake release 8.1 (Cooker) for i586
Linux werewolf 2.4.5-ac15 #2 SMP Sun Jun 17 02:12:45 CEST 2001 i686
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
 
 
 

getrusage vs /proc/pid/stat?

Post by Dan Kege » Thu, 21 Jun 2001 00:10:08



Quote:> I have just the same problem. getrusage() did not catch the CPU time for
> children, even if the man page said that. Now I am using times(2), that
> seems to work in Solaris, but gives nothing in Linux.

> I you look at time(1) manpage, it says time is implemented over the times(2)
> system call. But if I include that call, it gives me only zero.

> ????? time gives good results for summed CPU time, but my own call
> to times(2) fails ???

It could be that you have to wait() for the child before times()
includes it in 'children time'.

By the way, the source for time is easy to find.  Here's debian's
(just search for time.c, then click on 'main'):
http://src.openresources.com/debian/src/utils/HTML/mains.html

If that doesn't help, maybe the code I sent you that reads /proc/pid/stat
for all threads of interest will.  Either way, let me know...
- Dan
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. /proc/<pid>/stat does not jive with proc(5) man page

I am running RedHat 6.1 w/ kernel 2.2.12-20smp on my PentiumII PC.
Having read the man page on proc(5), I noticed that for all processes,
their associated stat file (in /proc/<pid>) has fields that don't
correspond to that mentioned in the man page.  In all stat files, I see
39 fields, but proc(5) describes only 35.

Anyone know what's up here?  Are there any C functions one can use to
seamlessly extract proc info into, say, a structure?

BTW, I noticed that nlist() appears not to be available in Linux, at
least in RH.  Is there a substitute for this?

--john

Sent via Deja.com http://www.deja.com/
Before you buy.

2. back-pressure bandwidth limitation

3. /proc/pid/stat array.c question

4. getting free space of a filesystem

5. kernel hang on reading /proc/<pid>/stat

6. News....I kow what I want to do...but...

7. /proc/<pid>/stat read hang with Mozilla in 2.4.14

8. Debian and start-stop-daemon...

9. Need help understanding /proc/pid/stat file

10. structure of /proc/<pid>/stat

11. socket vs pipe difference in /proc/pid/fd

12. Print tracer PID in /proc/<pid>/status

13. /proc/stat does not show disk_io stats for all IDE d isks