[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Finding CPU% of a linux task

Joe Van Dyk

1/10/2006 9:32:00 PM

Hi,

I'm writing a small Ruby module that can find how much cpu percentage
a given task is using. I'm doing it by getting the process id of the
task that I care about, going into proc, checking the stat file for
the process (which contains how many jiffies the task has consumed)
and averaging the change of that over time to get a running
percentage.

However, that doesn't capture threads or forked processes. If a
program starts a couple threads (or forks a child process), I then
have to figure out the cpu percentage of each of the child threads
(and their childs and their child's childs, and so on) and add them
together to get a total for the process.

I'm struggling to come up with an elegant way to solve this problem. Any ideas?

Thanks,
Joe


8 Answers

James Gray

1/10/2006 9:35:00 PM

0

On Jan 10, 2006, at 3:31 PM, Joe Van Dyk wrote:

> However, that doesn't capture threads or forked processes. If a
> program starts a couple threads (or forks a child process), I then
> have to figure out the cpu percentage of each of the child threads
> (and their childs and their child's childs, and so on) and add them
> together to get a total for the process.

Ruby's threads are in process, so they should already be in your
percentage, shouldn't they?

James Edward Gray II


Joe Van Dyk

1/10/2006 9:43:00 PM

0

On 1/10/06, James Edward Gray II <james@grayproductions.net> wrote:
> On Jan 10, 2006, at 3:31 PM, Joe Van Dyk wrote:
>
> > However, that doesn't capture threads or forked processes. If a
> > program starts a couple threads (or forks a child process), I then
> > have to figure out the cpu percentage of each of the child threads
> > (and their childs and their child's childs, and so on) and add them
> > together to get a total for the process.
>
> Ruby's threads are in process, so they should already be in your
> percentage, shouldn't they?

To clarify, these aren't Ruby processes I'm tracking.

Sample usage of my class:

pi = ProcessInfo.new <pid>
pi.cpu_percentage # returns the cpu % of the process
pi.running? # sees if the process is still running

etc

I added ProcessInfo#child_tasks, that searches /proc for all child
tasks of the process. But then, when I calculate the cpu% of the
process, I need to recursively go in and get all the cpu% of all the
child threads/processes of the process. And my code got ugly fast.


Michal Suchanek

1/10/2006 10:07:00 PM

0

On 1/10/06, Joe Van Dyk <joevandyk@gmail.com> wrote:> On 1/10/06, James Edward Gray II <james@grayproductions.net> wrote:> > On Jan 10, 2006, at 3:31 PM, Joe Van Dyk wrote:> >> > > However, that doesn't capture threads or forked processes. If a> > > program starts a couple threads (or forks a child process), I then> > > have to figure out the cpu percentage of each of the child threads> > > (and their childs and their child's childs, and so on) and add them> > > together to get a total for the process.> >> > Ruby's threads are in process, so they should already be in your> > percentage, shouldn't they?>> To clarify, these aren't Ruby processes I'm tracking.>> Sample usage of my class:>> pi = ProcessInfo.new <pid>> pi.cpu_percentage # returns the cpu % of the process> pi.running? # sees if the process is still running>> etc>> I added ProcessInfo#child_tasks, that searches /proc for all child> tasks of the process. But then, when I calculate the cpu% of the> process, I need to recursively go in and get all the cpu% of all the> child threads/processes of the process. And my code got ugly fast.What is wrong withclass ProcessInfodef direct_children <grep for children> <return array of ProcessInfo or []>enddef children direct_children.collect{|ch|ch.chilfren}.flatten!enddef cpu_sum sum = cpu_percentage children.each{|ch| sum += ch.cpu_percentage} sumendendThanksMichal-- Support the freedom of music!Maybe it's a weird genre .. but weird is *not* illegal.Maybe next time they will send a special forces commandoto your picnic .. because they think you are weird. www.music-versus-guns.org http://en.police...

Pierre Barbier de Reuille

1/10/2006 10:52:00 PM

0

Well, on Linux 2.6, the list of the threads is in :

/proc/[pid]/task

But it is not true for Linux 2.4 :(
And on 2.4, I really don't know if you can tell a process from a thread
from the exterior. At least, I see no difference in the /proc virtual
system.

But then, this discussion should be in
comp.os.linux.development.system, isn't it ?

Pierre

On Wed, 11 Jan 2006 06:42:54 +0900
Joe Van Dyk <joevandyk@gmail.com> wrote:

> On 1/10/06, James Edward Gray II <james@grayproductions.net> wrote:
> > On Jan 10, 2006, at 3:31 PM, Joe Van Dyk wrote:
> >
> > > However, that doesn't capture threads or forked processes. If a
> > > program starts a couple threads (or forks a child process), I then
> > > have to figure out the cpu percentage of each of the child threads
> > > (and their childs and their child's childs, and so on) and add
> > > them together to get a total for the process.
> >
> > Ruby's threads are in process, so they should already be in your
> > percentage, shouldn't they?
>
> To clarify, these aren't Ruby processes I'm tracking.
>
> Sample usage of my class:
>
> pi = ProcessInfo.new <pid>
> pi.cpu_percentage # returns the cpu % of the process
> pi.running? # sees if the process is still running
>
> etc
>
> I added ProcessInfo#child_tasks, that searches /proc for all child
> tasks of the process. But then, when I calculate the cpu% of the
> process, I need to recursively go in and get all the cpu% of all the
> child threads/processes of the process. And my code got ugly fast.
>
>


--
Do not sleep in a eucalyptus tree tonight.

Joe Van Dyk

1/10/2006 10:59:00 PM

0

On 1/10/06, Barbier de Reuille Pierre <p.barbierdereuille@free.fr> wrote:
> Well, on Linux 2.6, the list of the threads is in :
>
> /proc/[pid]/task
>
> But it is not true for Linux 2.4 :(
> And on 2.4, I really don't know if you can tell a process from a thread
> from the exterior. At least, I see no difference in the /proc virtual
> system.

For my purposes, I don't want to make a distinction between threads
and processes. I just want an accurate cpu percentage of a running
program (which includes all of its threads and child processes).


Ross Bamford

1/10/2006 11:18:00 PM

0

On Tue, 10 Jan 2006 22:59:27 -0000, Joe Van Dyk <joevandyk@gmail.com>
wrote:

> On 1/10/06, Barbier de Reuille Pierre <p.barbierdereuille@free.fr> wrote:
>> Well, on Linux 2.6, the list of the threads is in :
>>
>> /proc/[pid]/task
>>
>> But it is not true for Linux 2.4 :(
>> And on 2.4, I really don't know if you can tell a process from a thread
>> from the exterior. At least, I see no difference in the /proc virtual
>> system.
>
> For my purposes, I don't want to make a distinction between threads
> and processes. I just want an accurate cpu percentage of a running
> program (which includes all of its threads and child processes).
>

Since you're looking in /proc anyway I guess this is for unixy systems, so
_maybe_ the following is of use?

module Process
class << self
def cpu_percent(pid)
pgid = getpgid(pid)
ps = `ps -Ao pcpu,pgrp`.to_a
(ps[1..-1]).inject(0.0) do |sum,s|
if s =~ /([\d.]+)\s*([\d]+)/
tcpu, tpgid = $~.captures
(tpgid.to_i == pgid) ? sum + tcpu.to_f: sum
end
end
end
end
end

pid = (ARGV[0] || Process.pid).to_i
puts "#{pid}: #{Process.cpu_percent(pid)}"

Not a particularly clean one but maybe it gives a starting point? On my
system a quick test gives:

$ ps -o cmd,pcpu,pid,pgrp,sid
CMD %CPU PID PGRP SID
bash 0.0 4540 4540 4540
ruby -e fork { loop do 1000 2.2 4942 4942 4540
ruby -e fork { loop do 1000 4.3 4943 4942 4540
ps -o cmd,pcpu,pid,pgrp,sid 0.0 5393 5393 4540

$ ruby pinfo.rb 4942
4942: 6.5%

$ ruby pinfo.rb 4294
pinfo.rb:4:in `getpgid': No such process (Errno::ESRCH)
from pinfo.rb:4:in `cpu_percent'
from pinfo.rb:17

(that second one is a deliberate example :) )

Check out 'man ps' for the different args etc, and the proper output
format syntax if you're on non-GNU.

--
Ross Bamford - rosco@roscopeco.remove.co.uk

Joe Van Dyk

1/10/2006 11:30:00 PM

0

On 1/10/06, Joe Van Dyk <joevandyk@gmail.com> wrote:
> Hi,
>
> I'm writing a small Ruby module that can find how much cpu percentage
> a given task is using. I'm doing it by getting the process id of the
> task that I care about, going into proc, checking the stat file for
> the process (which contains how many jiffies the task has consumed)
> and averaging the change of that over time to get a running
> percentage.
>
> However, that doesn't capture threads or forked processes. If a
> program starts a couple threads (or forks a child process), I then
> have to figure out the cpu percentage of each of the child threads
> (and their childs and their child's childs, and so on) and add them
> together to get a total for the process.
>
> I'm struggling to come up with an elegant way to solve this problem. Any ideas?

I can't make heads or tails out of this behavior. 5463 is a thread,
btw. Linux 2.4.21, Ruby 1.8.4. When I do a directory glob of /proc/,
5463 isn't coming up.


irb(main):002:0> File.directory? "/proc/5463"
=> true

irb(main):003:0> Dir["/proc/5*"].sort
=> ["/proc/5", "/proc/5111", "/proc/5113", "/proc/5459", "/proc/5470",
"/proc/5477", "/proc/5486", "/proc/5487", "/proc/5653", "/proc/5654",
"/proc/5800", "/proc/5810", "/proc/5811"]

irb(main):004:0> Dir["/proc/5*"].include?("/proc/5463")
=> false

irb(main):005:0> # WTF
irb(main):006:0* exit

% ls -ld /proc/5463
dr-xr-xr-x 3 root games 0 Jan 10 15:26 /proc/5463/

% ls -l /proc/5463
ls: cannot read symbolic link /proc/5463/cwd: Permission denied
ls: cannot read symbolic link /proc/5463/root: Permission denied
ls: cannot read symbolic link /proc/5463/exe: Permission denied
total 0
-r--r--r-- 1 root games 0 Jan 10 15:26 cmdline
-r--r--r-- 1 root games 0 Jan 10 15:26 cpu
lrwxrwxrwx 1 root games 0 Jan 10 15:26 cwd
-r-------- 1 root games 0 Jan 10 15:26 environ
lrwxrwxrwx 1 root games 0 Jan 10 15:26 exe
dr-x------ 2 root games 0 Jan 10 15:26 fd/
-r-------- 1 root games 0 Jan 10 15:26 maps
-rw------- 1 root games 0 Jan 10 15:26 mem
-r--r--r-- 1 root games 0 Jan 10 15:26 mounts
lrwxrwxrwx 1 root games 0 Jan 10 15:26 root
-r--r--r-- 1 root games 0 Jan 10 15:26 stat
-r--r--r-- 1 root games 0 Jan 10 15:26 statm
-r--r--r-- 1 root games 0 Jan 10 15:26 status

% cat /proc/5463/status
Name: sccng.x
State: S (sleeping)
Tgid: 5459
Pid: 5463
PPid: 5459
TracerPid: 0
Uid: 0 0 0 0
Gid: 20 20 20 20
FDSize: 256
Groups: 0 1 2 3 4 6 10 1 2 3 4
VmSize: 147612 kB
VmLck: 147612 kB
VmRSS: 146648 kB
VmData: 58268 kB
VmStk: 776 kB
VmExe: 468 kB
VmLib: 11512 kB
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000080002e47
CapInh: 00000000ffffffff
CapPrm: 00000000ffffffff
CapEff: 00000000ffffffff


Joe Van Dyk

1/10/2006 11:47:00 PM

0

On 1/10/06, Joe Van Dyk <joevandyk@gmail.com> wrote:
> On 1/10/06, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > Hi,
> >
> > I'm writing a small Ruby module that can find how much cpu percentage
> > a given task is using. I'm doing it by getting the process id of the
> > task that I care about, going into proc, checking the stat file for
> > the process (which contains how many jiffies the task has consumed)
> > and averaging the change of that over time to get a running
> > percentage.
> >
> > However, that doesn't capture threads or forked processes. If a
> > program starts a couple threads (or forks a child process), I then
> > have to figure out the cpu percentage of each of the child threads
> > (and their childs and their child's childs, and so on) and add them
> > together to get a total for the process.
> >
> > I'm struggling to come up with an elegant way to solve this problem. Any ideas?
>
> I can't make heads or tails out of this behavior. 5463 is a thread,
> btw. Linux 2.4.21, Ruby 1.8.4. When I do a directory glob of /proc/,
> 5463 isn't coming up.
>
>
> irb(main):002:0> File.directory? "/proc/5463"
> => true
>
> irb(main):003:0> Dir["/proc/5*"].sort
> => ["/proc/5", "/proc/5111", "/proc/5113", "/proc/5459", "/proc/5470",
> "/proc/5477", "/proc/5486", "/proc/5487", "/proc/5653", "/proc/5654",
> "/proc/5800", "/proc/5810", "/proc/5811"]
>
> irb(main):004:0> Dir["/proc/5*"].include?("/proc/5463")
> => false
>
> irb(main):005:0> # WTF
> irb(main):006:0* exit
>
> % ls -ld /proc/5463
> dr-xr-xr-x 3 root games 0 Jan 10 15:26 /proc/5463/
>
> % ls -l /proc/5463
> ls: cannot read symbolic link /proc/5463/cwd: Permission denied
> ls: cannot read symbolic link /proc/5463/root: Permission denied
> ls: cannot read symbolic link /proc/5463/exe: Permission denied
> total 0
> -r--r--r-- 1 root games 0 Jan 10 15:26 cmdline
> -r--r--r-- 1 root games 0 Jan 10 15:26 cpu
> lrwxrwxrwx 1 root games 0 Jan 10 15:26 cwd
> -r-------- 1 root games 0 Jan 10 15:26 environ
> lrwxrwxrwx 1 root games 0 Jan 10 15:26 exe
> dr-x------ 2 root games 0 Jan 10 15:26 fd/
> -r-------- 1 root games 0 Jan 10 15:26 maps
> -rw------- 1 root games 0 Jan 10 15:26 mem
> -r--r--r-- 1 root games 0 Jan 10 15:26 mounts
> lrwxrwxrwx 1 root games 0 Jan 10 15:26 root
> -r--r--r-- 1 root games 0 Jan 10 15:26 stat
> -r--r--r-- 1 root games 0 Jan 10 15:26 statm
> -r--r--r-- 1 root games 0 Jan 10 15:26 status
>
> % cat /proc/5463/status
> Name: sccng.x
> State: S (sleeping)
> Tgid: 5459
> Pid: 5463
> PPid: 5459
> TracerPid: 0
> Uid: 0 0 0 0
> Gid: 20 20 20 20
> FDSize: 256
> Groups: 0 1 2 3 4 6 10 1 2 3 4
> VmSize: 147612 kB
> VmLck: 147612 kB
> VmRSS: 146648 kB
> VmData: 58268 kB
> VmStk: 776 kB
> VmExe: 468 kB
> VmLib: 11512 kB
> SigPnd: 0000000000000000
> ShdPnd: 0000000000000000
> SigBlk: 0000000000000000
> SigIgn: 0000000000001000
> SigCgt: 0000000080002e47
> CapInh: 00000000ffffffff
> CapPrm: 00000000ffffffff
> CapEff: 00000000ffffffff


Solved! I thought Ruby was being weird, shame on me.

Threads are represented in /proc with a '.' in front of the id. i.e.
/proc/.5463. For some reason though, I can access /proc/5463, but
/proc/5463 doesn't show up in directory globs.

Joe