Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/services/console/lib/procmem/proc_smaps.py
diff options
context:
space:
mode:
Diffstat (limited to 'services/console/lib/procmem/proc_smaps.py')
-rw-r--r--services/console/lib/procmem/proc_smaps.py129
1 files changed, 129 insertions, 0 deletions
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