Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/services/console/lib
diff options
context:
space:
mode:
Diffstat (limited to 'services/console/lib')
-rw-r--r--services/console/lib/Makefile.am4
-rw-r--r--services/console/lib/procmem/Makefile.am8
-rw-r--r--services/console/lib/procmem/__init__.py0
-rw-r--r--services/console/lib/procmem/analysis.py30
-rw-r--r--services/console/lib/procmem/proc.py100
-rw-r--r--services/console/lib/procmem/proc_smaps.py129
6 files changed, 271 insertions, 0 deletions
diff --git a/services/console/lib/Makefile.am b/services/console/lib/Makefile.am
new file mode 100644
index 0000000..16782d7
--- /dev/null
+++ b/services/console/lib/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = procmem
+
+sugardir = $(pkgdatadir)/shell/console/lib
+sugar_PYTHON =
diff --git a/services/console/lib/procmem/Makefile.am b/services/console/lib/procmem/Makefile.am
new file mode 100644
index 0000000..257c13f
--- /dev/null
+++ b/services/console/lib/procmem/Makefile.am
@@ -0,0 +1,8 @@
+
+sugardir = $(pkgdatadir)/shell/console/lib/procmem
+
+sugar_PYTHON = \
+ __init__.py \
+ proc.py \
+ proc_smaps.py \
+ analysis.py
diff --git a/services/console/lib/procmem/__init__.py b/services/console/lib/procmem/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/console/lib/procmem/__init__.py
diff --git a/services/console/lib/procmem/analysis.py b/services/console/lib/procmem/analysis.py
new file mode 100644
index 0000000..d2a247a
--- /dev/null
+++ b/services/console/lib/procmem/analysis.py
@@ -0,0 +1,30 @@
+import proc, proc_smaps
+
+class Analysis:
+
+ pid = 0
+
+ def __init__(self, pid):
+ self.pid = pid
+
+ def DirtyRSS(self):
+ smaps = proc_smaps.ProcSmaps(self.pid)
+ dirty = []
+
+ private = 0
+ shared = 0
+
+ for map in smaps.mappings:
+ private += map.private_dirty
+ shared += map.shared_dirty
+
+ dirty = {"private": int(private), "shared": int(shared)}
+
+ return dirty
+
+ def ApproxRealMemoryUsage(self):
+ maps = proc_smaps.ProcMaps(self.pid)
+ size = (maps.clean_size/1024)
+
+ return size
+ \ No newline at end of file
diff --git a/services/console/lib/procmem/proc.py b/services/console/lib/procmem/proc.py
new file mode 100644
index 0000000..729aa13
--- /dev/null
+++ b/services/console/lib/procmem/proc.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+
+import sys, os
+import string
+
+class ProcInfo:
+
+ dir_path = "/proc/" # Our cute Proc File System
+ status_file = "status"
+ stat_file = "stat"
+
+ proc_list = [] # Our PID list :D
+ proc_info = [] #
+
+ def __init__(self):
+ self.proc_list = self.Get_PID_List()
+
+ # Returns Process List
+ def Get_PID_List(self):
+ list = []
+
+ # Exists our procfs ?
+ if os.path.isdir(self.dir_path):
+ # around dir entries
+ for f in os.listdir(self.dir_path):
+ if os.path.isdir(self.dir_path+f) & str.isdigit(f):
+ list.append(int(f))
+
+ return list
+
+ def MemoryInfo(self, pid):
+ # Path
+ pidfile = self.dir_path + str(pid) + "/stat"
+ try:
+ infile = open(pidfile, "r")
+ except:
+ print "Error trying " + pidfile
+ return None
+
+ # Parsing data , check 'man 5 proc' for details
+ data = infile.read().split()
+
+ infile.close()
+
+ state_dic = {
+ 'R': 'Running',
+ 'S': 'Sleeping',
+ 'D': 'Disk sleep',
+ 'Z': 'Zombie',
+ 'T': 'Traced/Stopped',
+ 'W': 'Paging'
+ }
+
+ # user and group owners
+ pidstat = os.stat(pidfile)
+
+ info = {
+ 'pid': int(data[0]), # Process ID
+ 'name': data[1].strip('()'), # Process name
+ 'state': data[2], # Process State, ex: R|S|D|Z|T|W
+ 'state_name': state_dic[data[2]], # Process State name, ex: Running, sleeping, Zombie, etc
+ 'ppid': int(data[3]), # Parent process ID
+ 'utime': int(data[13]), # Used jiffies in user mode
+ 'stime': int(data[14]), # Used jiffies in kernel mode
+ 'start_time': int(data[21]), # Process time from system boot (jiffies)
+ 'vsize': int(data[22]), # Virtual memory size used (bytes)
+ 'rss': int(data[23])*4, # Resident Set Size (bytes)
+ 'user_id': pidstat.st_uid, # process owner
+ 'group_id': pidstat.st_gid # owner group
+ }
+
+ return info
+
+
+ # Returns the CPU usage expressed in Jiffies
+ def get_CPU_usage(self, cpu_hz, used_jiffies, start_time):
+
+ # Uptime info
+ uptime_file = self.dir_path + "/uptime"
+ try:
+ infile = file(uptime_file, "r")
+ except:
+ print "Error trying uptime file"
+ return None
+
+ uptime_line = infile.readline()
+ uptime = string.split(uptime_line, " ",2)
+
+ infile.close()
+
+ # System uptime, from /proc/uptime
+ uptime = float(uptime[0])
+
+ # Jiffies
+ avail_jiffies = (uptime * cpu_hz) - start_time
+
+ cpu_usage = {'used_jiffies': used_jiffies, 'avail_jiffies': avail_jiffies}
+
+ return cpu_usage
+
diff --git a/services/console/lib/procmem/proc_smaps.py b/services/console/lib/procmem/proc_smaps.py
new file mode 100644
index 0000000..9416c52
--- /dev/null
+++ b/services/console/lib/procmem/proc_smaps.py
@@ -0,0 +1,129 @@
+####################################################################
+# This class open the /proc/PID/maps and /proc/PID/smaps files
+# to get useful information about the real memory usage
+####################################################################
+#!/usr/bin/env python
+
+import os
+
+# Parse the /proc/PID/smaps file
+class ProcSmaps:
+
+ mappings = [] # Devices information
+
+ def __init__(self, pid):
+
+ smapfile = "/proc/%s/smaps" % pid
+ self.mappings = []
+
+ # Coded by Federico Mena (script)
+ try:
+ infile = open(smapfile, "r")
+ input = infile.read()
+ infile.close()
+ except:
+ print "Error trying " + smapfile
+ return
+
+ lines = input.splitlines()
+
+ num_lines = len (lines)
+ line_idx = 0
+
+ # 08065000-08067000 rw-p 0001c000 03:01 147613 /opt/gnome/bin/evolution-2.6
+ # Size: 8 kB
+ # Rss: 8 kB
+ # Shared_Clean: 0 kB
+ # Shared_Dirty: 0 kB
+ # Private_Clean: 8 kB
+ # Private_Dirty: 0 kB
+
+ while num_lines > 0:
+ fields = lines[line_idx].split (" ", 5)
+ if len (fields) == 6:
+ (offsets, permissions, bin_permissions, device, inode, name) = fields
+ else:
+ (offsets, permissions, bin_permissions, device, inode) = fields
+ name = ""
+
+ size = self.parse_smaps_size_line (lines[line_idx + 1])
+ rss = self.parse_smaps_size_line (lines[line_idx + 2])
+ shared_clean = self.parse_smaps_size_line (lines[line_idx + 3])
+ shared_dirty = self.parse_smaps_size_line (lines[line_idx + 4])
+ private_clean = self.parse_smaps_size_line (lines[line_idx + 5])
+ private_dirty = self.parse_smaps_size_line (lines[line_idx + 6])
+ name = name.strip ()
+
+ mapping = Mapping (size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name)
+ self.mappings.append (mapping)
+
+ num_lines -= 7
+ line_idx += 7
+
+ # Parses a line of the form "foo: 42 kB" and returns an integer for the "42" field
+ def parse_smaps_size_line (self, line):
+ # Rss: 8 kB
+ fields = line.split ()
+ return int(fields[1])
+
+class Mapping:
+ def __init__ (self, size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name):
+ self.size = size
+ self.rss = rss
+ self.shared_clean = shared_clean
+ self.shared_dirty = shared_dirty
+ self.private_clean = private_clean
+ self.private_dirty = private_dirty
+ self.permissions = permissions
+ self.name = name
+
+# Parse /proc/PID/maps file to get the clean memory usage by process,
+# we avoid lines with backed-files
+class ProcMaps:
+
+ clean_size = 0
+
+ def __init__(self, pid):
+ mapfile = "/proc/%s/maps" % pid
+
+ try:
+ infile = open(mapfile, "r")
+ except:
+ print "Error trying " + mapfile
+ return None
+
+ sum = 0
+ to_data_do = {
+ "[anon]": self.parse_size_line,
+ "[heap]": self.parse_size_line
+ }
+
+ for line in infile:
+ arr = line.split()
+
+ # Just parse writable mapped areas
+ if arr[1][1] != "w":
+ continue
+
+ if len(arr) == 6:
+ # if we got a backed-file we skip this info
+ if os.path.isfile(arr[5]):
+ continue
+ else:
+ line_size = to_data_do.get(arr[5], self.skip)(line)
+ sum += line_size
+ else:
+ line_size = self.parse_size_line(line)
+ sum += line_size
+
+ infile.close()
+ self.clean_size = sum
+
+ def skip(self, line):
+ return 0
+
+ # Parse a maps line and return the mapped size
+ def parse_size_line(self, line):
+ start, end = line.split()[0].split('-')
+ size = int(end, 16) - int(start, 16)
+ return size