Created — forked from seanosulliv/memuse.py

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View memuse.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#!/usr/bin/env python
 
 
# Try to determine how much RAM is currently being used per program.
 
# Notes:
#
# All interpreted programs where the interpreter is started
# by the shell or with env, will be merged to the interpreter
# (as that's what's given to exec). For e.g. all python programs
# starting with "#!/usr/bin/env python" will be grouped under python.
# You can change this by changing comm= to args= below but that will
# have the undesirable affect of splitting up programs started with
# differing parameters (for e.g. mingetty tty[1-6]).
#
# For older 2.6 kernels and later 2.4 redhat kernels (rmap vm without smaps)
# it can not be accurately determined how many pages are shared
# between processes in general or within a program in our case:
# http://lkml.org/lkml/2005/7/6/250
# A warning is printed if overestimation is possible.
#
# The shared calculation below will factor out shared text and
# libs etc. within a program, but not between programs. So there
# will always be some overestimation. This will be the same for
# all processes that just use libc for e.g. but more for others
# that use larger shared libs like gnome, kde etc.
#
# I don't take account of memory allocated for a program
# by other programs. For e.g. memory used in the X server for
# a program could be determined, but is not.
#
# This script assumes threads are already merged by ps
 
import sys, os, string
PAGESIZE=os.sysconf("SC_PAGE_SIZE")/1024 #KiB
our_pid=os.getpid()
 
def shared_val_accurate():
"""http://wiki.apache.org/spamassassin/TopSharedMemoryBug"""
kernel_ver=open("/proc/sys/kernel/osrelease").readline()[:3]
if kernel_ver == "2.4":
if open("/proc/meminfo").read().find("Inact_") == -1:
return 1
return 0
elif kernel_ver == "2.6":
if os.path.exists("/proc/"+str(os.getpid())+"/smaps"):
return 1
return 0
 
def getShared(pid):
if os.path.exists("/proc/"+str(pid)+"/smaps"):
shared_lines=[line
for line in open("/proc/"+str(pid)+"/smaps").readlines()
if line.find("Shared")!=-1]
return sum([int(line.split()[1]) for line in shared_lines])
else:
return int(open("/proc/"+str(pid)+"/statm").readline().split()[2])*PAGESIZE
 
cmds={}
shareds={}
for line in os.popen("ps -e -o rss=,pid=,comm=").readlines():
size, pid, cmd = map(string.strip,line.strip().split(None,2))
if int(pid) == our_pid:
continue #no point counting this process
try:
shared=getShared(pid)
except:
continue #ps gone away
if shareds.get(cmd):
if shareds[cmd] < shared:
shareds[cmd]=shared
else:
shareds[cmd]=shared
#Note shared is always a subset of rss (trs is not always)
cmds[cmd]=cmds.setdefault(cmd,0)+int(size)-shared
 
#Add max shared mem for each program
for cmd in cmds.keys():
cmds[cmd]=cmds[cmd]+shareds[cmd]
 
sort_list = cmds.items()
sort_list.sort(lambda x,y:cmp(x[1],y[1]))
sort_list=filter(lambda x:x[1],sort_list) #get rid of zero sized processes (kernel threads)
 
#The following matches "du -h" output
def human(num, power="K"):
powers=["K","M","G","T"]
while num >= 1000:
num /= 1024.0
power=powers[powers.index(power)+1]
human(num,power)
return "%.1f%s" % (num,power)
 
for cmd in sort_list:
print "%6s %s" % (human(cmd[1]), cmd[0])
 
#if not shared_val_accurate():
# sys.stderr.write("\nWarning: Shared memory is not reported correctly by this system.\n")
# sys.stderr.write("Values reported could be too large.\n")
 
 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.