blob: 1d23af90d769d07b0cbf122d322ba2d34ab9a230 [file] [log] [blame]
Ihar Hrachyshka2b4735f2017-02-10 06:17:37 +00001#!/usr/bin/env python
2
3# This tool lists processes that lock memory pages from swapping to disk.
4
5import re
6import subprocess
7
8import psutil
9
10
11SUMMARY_REGEX = re.compile(r".*\s+(?P<locked>[\d]+)\s+KB")
12
13
14def main():
15 try:
16 print _get_report()
17 except Exception as e:
18 print "Failure listing processes locking memory: %s" % str(e)
19
20
21def _get_report():
22 mlock_users = []
23 for proc in psutil.process_iter():
24 pid = proc.pid
25 # sadly psutil does not expose locked pages info, that's why we
26 # call to pmap and parse the output here
27 try:
28 out = subprocess.check_output(['pmap', '-XX', str(pid)])
29 except subprocess.CalledProcessError as e:
30 # 42 means process just vanished, which is ok
31 if e.returncode == 42:
32 continue
33 raise
34 last_line = out.splitlines()[-1]
35
36 # some processes don't provide a memory map, for example those
37 # running as kernel services, so we need to skip those that don't
38 # match
39 result = SUMMARY_REGEX.match(last_line)
40 if result:
41 locked = int(result.group('locked'))
42 if locked:
43 mlock_users.append({'name': proc.name(),
44 'pid': pid,
45 'locked': locked})
46
47 # produce a single line log message with per process mlock stats
48 if mlock_users:
49 return "; ".join(
50 "[%(name)s (pid:%(pid)s)]=%(locked)dKB" % args
51 # log heavy users first
52 for args in sorted(mlock_users, key=lambda d: d['locked'])
53 )
54 else:
55 return "no locked memory"
56
57
58if __name__ == "__main__":
59 main()