-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmemtree.py
97 lines (72 loc) · 2.25 KB
/
memtree.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
from distutils.log import debug
import time
import signal
import subprocess
from typing import Tuple
import psutil
import click
import json
def print_memory_usage(ps, save_json):
total = 0.0
total_results = []
parts = []
for p in ps:
# use the "unique size set" for now:
try:
part = p.memory_full_info().rss
parts.append((p.pid, part))
total += part
except psutil.NoSuchProcess:
print('Process no longer exist')
total_result = {'parts': parts,
'result': total}
parts_fmt = [
f"{pid:7}: {part/1024.0/1024.0:.2f}MiB"
for (pid, part) in parts
]
parts_fmt = "\n\t".join(parts_fmt)
print(f"total: {total/1024.0/1024.0:.2f}MiB")
print("\t" + parts_fmt)
return total_result
def get_children(main_process):
children = [
pr for pr in psutil.process_iter() if pr.ppid() == main_process.pid
]
return children
def run_command(cmd: Tuple[str]):
p = subprocess.Popen(cmd)
return p.pid, p
@click.command()
@click.option('-s', '--save-json', type=str)
@click.option('-p', '--pid', type=int)
@click.argument('cmd', nargs=-1, type=str)
def main(cmd, pid, save_json):
if pid is None and not cmd:
click.echo("either specify `pid` or `cmd`")
return
subp = None
if pid is None:
pid, subp = run_command(cmd)
print(f"monitoring pid {pid}")
main_process = psutil.Process(pid=pid)
result_time_stamp = []
try:
while True:
time_stamp = time.time()
children = get_children(main_process)
processes = [main_process] + children
total_result = print_memory_usage(processes, save_json)
time.sleep(0.2)
total_result['time_stamp'] = time_stamp
result_time_stamp.append(total_result)
with open(save_json, 'w') as f:
json.dump(result_time_stamp, f)
if subp is not None:
if subp.poll() is not None:
break
finally:
if subp is not None:
subp.send_signal(signal.SIGINT)
subp.wait()
if __name__ == "__main__":
main()