From cae78d70415923c0deabd518f23dc534f11cfacd Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Mon, 08 Jan 2007 17:06:59 +0000 Subject: Rework the console to use autoactivation, move it in services/ --- (limited to 'services/console/lib/procmem/proc_smaps.py') 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 -- cgit v0.9.1