blob: 2e0fed88724cddb9ee4e2a6c779c6cb73dfd278a [file] [log] [blame]
Ved-vampir98a99172015-03-17 14:58:15 +03001#!/usr/bin/env python
2
Ved-vampir501065c2015-03-17 16:16:57 +03003# Based on ps_mem.py:
Ved-vampir98a99172015-03-17 14:58:15 +03004# Licence: LGPLv2
5# Author: P@draigBrady.com
6# Source: http://www.pixelbeat.org/scripts/ps_mem.py
Ved-vampir98a99172015-03-17 14:58:15 +03007# http://github.com/pixelb/scripts/commits/master/scripts/ps_mem.py
8
Ved-vampir98a99172015-03-17 14:58:15 +03009import errno
10import os
11import sys
12
Ved-vampir98a99172015-03-17 14:58:15 +030013
14
Ved-vampir98a99172015-03-17 14:58:15 +030015class Proc:
16 def __init__(self):
17 uname = os.uname()
18 if uname[0] == "FreeBSD":
19 self.proc = '/compat/linux/proc'
20 else:
21 self.proc = '/proc'
22
23 def path(self, *args):
24 return os.path.join(self.proc, *(str(a) for a in args))
25
26 def open(self, *args):
27 try:
28 return open(self.path(*args))
29 except (IOError, OSError):
30 val = sys.exc_info()[1]
31 if (val.errno == errno.ENOENT or # kernel thread or process gone
32 val.errno == errno.EPERM):
33 raise LookupError
34 raise
35
Ved-vampir98a99172015-03-17 14:58:15 +030036
Ved-vampir98a99172015-03-17 14:58:15 +030037def kernel_ver():
Ved-vampir501065c2015-03-17 16:16:57 +030038 """ Return (major,minor,release)"""
39 proc = Proc()
Ved-vampir98a99172015-03-17 14:58:15 +030040 kv = proc.open('sys/kernel/osrelease').readline().split(".")[:3]
41 last = len(kv)
42 if last == 2:
43 kv.append('0')
44 last -= 1
45 while last > 0:
46 for char in "-_":
47 kv[last] = kv[last].split(char)[0]
48 try:
49 int(kv[last])
50 except:
51 kv[last] = 0
52 last -= 1
53 return (int(kv[0]), int(kv[1]), int(kv[2]))
54
55
Ved-vampir98a99172015-03-17 14:58:15 +030056#Note shared is always a subset of rss (trs is not always)
57def getMemStats(pid):
Ved-vampir501065c2015-03-17 16:16:57 +030058 """ Return memory data of pid in format (Private, Shared) """
59
60 PAGESIZE = os.sysconf("SC_PAGE_SIZE") / 1024 #KiB
61 proc = Proc()
62
Ved-vampir98a99172015-03-17 14:58:15 +030063 Private_lines = []
64 Shared_lines = []
65 Pss_lines = []
Ved-vampir501065c2015-03-17 16:16:57 +030066
Ved-vampir98a99172015-03-17 14:58:15 +030067 Rss = (int(proc.open(pid, 'statm').readline().split()[1])
68 * PAGESIZE)
Ved-vampir501065c2015-03-17 16:16:57 +030069
Ved-vampir98a99172015-03-17 14:58:15 +030070 if os.path.exists(proc.path(pid, 'smaps')): #stat
Ved-vampir98a99172015-03-17 14:58:15 +030071 for line in proc.open(pid, 'smaps').readlines(): #open
72 # Note we checksum smaps as maps is usually but
73 # not always different for separate processes.
Ved-vampir98a99172015-03-17 14:58:15 +030074 if line.startswith("Shared"):
75 Shared_lines.append(line)
76 elif line.startswith("Private"):
77 Private_lines.append(line)
78 elif line.startswith("Pss"):
79 have_pss = 1
80 Pss_lines.append(line)
Ved-vampir98a99172015-03-17 14:58:15 +030081 Shared = sum([int(line.split()[1]) for line in Shared_lines])
82 Private = sum([int(line.split()[1]) for line in Private_lines])
83 #Note Shared + Private = Rss above
84 #The Rss in smaps includes video card mem etc.
85 if have_pss:
86 pss_adjust = 0.5 # add 0.5KiB as this avg error due to trunctation
87 Pss = sum([float(line.split()[1])+pss_adjust for line in Pss_lines])
88 Shared = Pss - Private
Ved-vampir501065c2015-03-17 16:16:57 +030089 elif (2, 6, 1) <= kernel_ver() <= (2, 6, 9):
Ved-vampir98a99172015-03-17 14:58:15 +030090 Shared = 0 #lots of overestimation, but what can we do?
91 Private = Rss
92 else:
93 Shared = int(proc.open(pid, 'statm').readline().split()[2])
94 Shared *= PAGESIZE
95 Private = Rss - Shared
Ved-vampir501065c2015-03-17 16:16:57 +030096 return (Private, Shared)