suaveant has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to figure out how to calculate a process' percent cpu usage using the data out of /proc/PID/*

I am assuming it needs to be calculated since I am not seeing a field anywhere in there.

I am already parsing the data, but having trouble figuring out what calculation I need to do. I am looking for the same value top displays as %CPU.

I'm trying to do this purely in perl, without C or running ps in backticks...

                - Ant
                - Some of my best work - (1 2 3)

Replies are listed 'Best First'.
Re: Calculating percent cpu in linux?
by eXile (Priest) on May 03, 2005 at 01:57 UTC
    If you really don't want to use ps, I'd look for the definite answer in the source code of a ps/top version that reads from /proc : http://procps.sourceforge.net/ Please post if you found the answer, because I'm kind of curious too.
Re: Calculating percent cpu in linux?
by scmason (Monk) on May 02, 2005 at 21:27 UTC
    Withdrew my comment after I saw you did not want to use PS (of course, you wouldn't use it in backticks if you wanted the output, you would use something like:

    open(PS,"ps|"); while (my $thisLine = <PS>){ #do something }
    Kind of thing.
Re: Calculating percent cpu in linux?
by scmason (Monk) on May 02, 2005 at 23:55 UTC
    I am a little confused by this question, I have looked on several linux boxes (SuSe, Fedora and Mandrake) and have yet to find a '/proc/PID/' directory. In all of these machines, this info was stored under a directory bearing the pid-number in the top level of the proc filesystem (for instance, init has PID 1 and its info is located in /proc/1/)

    Maybe that is what you mean. If not, and your machine actually does have a /proc/PID/* directory, then this does not seem like a very portable manner of doing it. Perhaps you should rethink using ps, as it should be very portable.

    If you really want to use the 'pure perl' method, then you will not reinvent the wheel. Look here at Proc::ProcessTable from... you guessed it CPAN. It will do everything you need.

    Good luck.

      Well.. actually this is for the Linux half of a Linux/Solaris library. I could use ps, but from years of using ps I tend not to entirely trust parsing the output.

      And there are a couple problems with Proc::ProcessTable... 1) it is mostly C, 2) I can't seem to see a way to call for individual pids in it... maybe I am reading the docs wrong, but it looks like you can only get the whole processtable as a snapshot, basically...

                      - Ant
                      - Some of my best work - (1 2 3)

Re: Calculating percent cpu in linux?
by ambrus (Abbot) on May 03, 2005 at 07:04 UTC

    From /proc/$PID/stat, you can get the amount of cpu time a process has used in user and system mode (similar to times, but for other processes). If you examine this twice, with a few seconds of delay between them, you get the amount of time the cpu spent on it. You then divide this amount with the delay, and there you are. (Of course, on an smp machine you may or may not want to divide with the number of cpus, depending on what you mean by cpu-percent.)

    There must be a faster wat though, as ps u can return the percent-cpu faster. As eXile has recommended, get procps from http://procps.sf.net/.

Re: Calculating percent cpu in linux?
by gam3 (Curate) on May 03, 2005 at 09:42 UTC
    Well after a bit of work I have come up with the following: By default this is including reaped children. I don't think ps does.

    Update: fix to %CPU in printf per zentara.

    -- gam3
    A picture is worth a thousand words, but takes 200K.
      A minor nitpick...Invalid conversion in printf: "%C" at ./cpu-usage

      But what I really wanted to say, is I often use a similar script I wrote called MeM. It pops up a Tk window in the upper left corner of the screen, and constantly updates and reports memory usage of a pid( or the calling script). Anyways, you could easily modify the code, to report cpu usage. Here is the code, just change it to run your code, and name it accordingly.

      package MeM; use warnings; use strict; use vars qw(@ISA @EXPORT_OK); @ISA = qw(Exporter); # inherit the import() from Exporter.pm @EXPORT_OK = qw(); # list of things to export if asked to my $pid =$$; if (fork() == 0) { require Tk; my $mw = new MainWindow; $mw->overrideredirect(1); my $t = $mw->Label(-text => '', -bg => 'black', -fg => 'yellow')-> +pack; $0 = 'MeM'; my $id = Tk::After->new($mw, 1000, 'repeat', [ \&refresh, $pid ]); Tk::MainLoop(); sub refresh { my $pid = shift; #asmutils version of cat my @size = split "\n", `/home/zentara/perl5lib/cat /proc/$pid/ +status`; #my @size = split "\n", `cat /proc/$pid/status`; (my $vmsize) = grep { /VmSize/ } @size; my (undef, $size) = split ' ', $vmsize; $t->configure(-text => "PID: $pid -> $size"); if ($size eq '') { exit } } } 1;

      I'm not really a human, but I play one on earth. flash japh
      Ahh.. that looks like it works.. thanks a lot!

                      - Ant
                      - Some of my best work - (1 2 3)