1 import os
2 import re
3 import die
4
7
9 """@rtype: L{float}
10 @return: Big (>1) when the system is really hurting for memory. Small (<0.5) when things are going well.
11 Also, by way of the amount of dirty memory, it indirectly looks at the rate of writing to the disk.
12 """
13 SWAPFAC = 1.0
14 x = {}
15 for l in open("/proc/meminfo", "r"):
16 kvu = l.strip().split()
17 if len(kvu) > 1:
18 x[kvu[0].strip().rstrip(':')] = float(kvu[1])
19 swap = SWAPFAC*(x['SwapTotal']-x['SwapFree'])/x['MemTotal']
20 active = x['Active'] / x['MemTotal']
21 dirty = 10 * x['Dirty'] / x['MemTotal']
22 if verbose:
23 die.info("mem_pressure: sw=%.2f ac=%.2f d=%.2f" % (swap, active, dirty))
24 return swap + active + dirty
25
26
27 _ncpu = None
29 global _ncpu
30 if _ncpu is not None:
31 return _ncpu
32 n = 0
33 for l in open("/proc/cpuinfo", "r"):
34 if l.startswith('processor'):
35 n += 1
36 assert n > 0
37 _ncpu = n
38 return n
39
40 get_ncpu = ncpu
41 get_loadavg = load_avg
42
43
44
45
46
47 PROC = '/proc'
48
50 _spat = re.compile(r'(\d+) \((.*)\) ([A-Z]) ([0-9]+) ([0-9 -]+)')
51 _map = { 'minflt': 5, 'cminflt': 6, 'majflt': 7, 'cmajflt': 8,
52 'utime': 9, 'stime': 10, 'cutime': 11, 'cstime': 12,
53 'priority': 13, 'nice': 14, 'num_threads': 15,
54 'vsize': 18, 'rss': 19, 'rsslim': 20
55 }
56
57
59 self.pid = pid
60 fp = open(os.path.join(PROC, str(pid), 'stat'), 'r')
61 self.uid = os.fstat(fp.fileno()).st_uid
62 s = fp.read()
63 m = self._spat.match(s)
64 if not m:
65 raise ValueError, "/proc/pid/stat doesn't match pattern: %s" % s
66 self.comm = m.group(2)
67 self.state = m.group(3)
68 self.ppid = int(m.group(4))
69 self._more = m.group(5).split()
70
73
74
75
76 -def load_now(my_weight=1, other_weight=2, d_weight=0.5, ignore=None, verbose=False):
77 me = os.getuid()
78 mypid = os.getpid()
79 myload = 0
80 oload = 0
81 kload = 0
82 dload = 0
83 for d in os.listdir(PROC):
84 try:
85 pid = int(d)
86 except ValueError:
87 continue
88 if pid == mypid:
89 continue
90 try:
91 fields = pstat(pid)
92 except (ValueError, IOError):
93 continue
94 if ignore is not None and ignore(pid, fields.ppid, fields.comm):
95 continue
96 if fields.state in "RD":
97 if verbose:
98 die.info("pid=%d proc=%s %s" % (fields.pid, fields.comm, fields.state))
99 if fields.uid == me:
100 myload += 1
101 elif fields.uid == 0:
102 kload += 1
103 else:
104 oload += 1
105 if fields.state == "D":
106 dload += 1
107
108 load = float(myload*my_weight + oload*other_weight + dload*d_weight)
109 load += kload * float((myload+1)*my_weight + oload*other_weight) / float(myload+1+oload)
110 return load
111
112
114 """@return: positive numbers if the process is niced; negative numbers if not.
115 @rtype: float in the range [-0.5, 0.5]
116 """
117 ni = pstat(os.getpid()).nice
118 return float(ni-9.5)/19.0
119
120
121 if __name__ == '__main__':
122 print 'ncpu=', ncpu()
123 print 'niceness=', niceness()
124 for i in range(5):
125 print 'load_now=', load_now(verbose=True), load_now(1,0,0), load_now(0,1,0), load_now(0,0,1)
126 print 'mem_pressure', mem_pressure(verbose=True)
127