Finding CPU% of a linux task

J

Joe Van Dyk

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 i=
deas?

Thanks,
Joe
 
J

James Edward Gray II

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
 
J

Joe Van Dyk

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 =3D 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.
 
B

Barbier de Reuille Pierre

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
 
J

Joe Van Dyk

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).
 
R

Ross Bamford

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.
 
J

Joe Van Dyk

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"
=3D> true

irb(main):003:0> Dir["/proc/5*"].sort
=3D> ["/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")
=3D> 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
 
J

Joe Van Dyk

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. A=
ny 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"
=3D> true

irb(main):003:0> Dir["/proc/5*"].sort
=3D> ["/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")
=3D> 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top