2020-01-17 12:23:21 -07:00
|
|
|
#!/usr/bin/env python3
|
2020-05-28 16:05:04 -06:00
|
|
|
# type: ignore
|
2020-01-17 12:23:21 -07:00
|
|
|
'''
|
|
|
|
System tools like top/htop can only show current cpu usage values, so I write this script to do statistics jobs.
|
|
|
|
Features:
|
2020-07-08 20:42:03 -06:00
|
|
|
Use psutil library to sample cpu usage(avergage for all cores) of openpilot processes, at a rate of 5 samples/sec.
|
2020-01-17 12:23:21 -07:00
|
|
|
Do cpu usage statistics periodically, 5 seconds as a cycle.
|
|
|
|
Caculate the average cpu usage within this cycle.
|
|
|
|
Caculate minumium/maximium/accumulated_average cpu usage as long term inspections.
|
|
|
|
Monitor multiple processes simuteneously.
|
|
|
|
Sample usage:
|
|
|
|
root@localhost:/data/openpilot$ python selfdrive/debug/cpu_usage_stat.py boardd,ubloxd
|
|
|
|
('Add monitored proc:', './boardd')
|
|
|
|
('Add monitored proc:', 'python locationd/ubloxd.py')
|
|
|
|
boardd: 1.96%, min: 1.96%, max: 1.96%, acc: 1.96%
|
|
|
|
ubloxd.py: 0.39%, min: 0.39%, max: 0.39%, acc: 0.39%
|
|
|
|
'''
|
2020-06-02 17:29:32 -06:00
|
|
|
import psutil
|
|
|
|
import time
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import numpy as np
|
|
|
|
import argparse
|
|
|
|
import re
|
|
|
|
from collections import defaultdict
|
|
|
|
|
2020-01-17 12:23:21 -07:00
|
|
|
|
|
|
|
# Do statistics every 5 seconds
|
|
|
|
PRINT_INTERVAL = 5
|
|
|
|
SLEEP_INTERVAL = 0.2
|
|
|
|
|
|
|
|
monitored_proc_names = [
|
2020-09-16 16:47:44 -06:00
|
|
|
# openpilot procs
|
|
|
|
'controlsd', 'locationd', 'loggerd','plannerd',
|
|
|
|
'ubloxd', 'thermald', 'uploader', 'deleter', 'radard', 'logmessaged', 'tombstoned',
|
|
|
|
'logcatd', 'proclogd', 'boardd', 'pandad', './ui', 'ui', 'calibrationd', 'params_learner', 'modeld', 'dmonitoringd',
|
|
|
|
'dmonitoringmodeld', 'camerad', 'sensord', 'updated', 'gpsd', 'athena', 'locationd', 'paramsd',
|
|
|
|
|
2020-10-06 22:12:38 -06:00
|
|
|
'ai.comma.plus.offroad',
|
|
|
|
|
2020-09-16 16:47:44 -06:00
|
|
|
# android procs
|
|
|
|
'SurfaceFlinger', 'sensors.qcom'
|
|
|
|
]
|
|
|
|
|
2020-01-17 12:23:21 -07:00
|
|
|
cpu_time_names = ['user', 'system', 'children_user', 'children_system']
|
|
|
|
|
|
|
|
timer = getattr(time, 'monotonic', time.time)
|
|
|
|
|
2020-06-02 17:29:32 -06:00
|
|
|
|
2020-01-17 12:23:21 -07:00
|
|
|
def get_arg_parser():
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="Unlogger and UI",
|
|
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
|
|
|
|
|
|
parser.add_argument("proc_names", nargs="?", default='',
|
|
|
|
help="Process names to be monitored, comma seperated")
|
|
|
|
parser.add_argument("--list_all", action='store_true',
|
|
|
|
help="Show all running processes' cmdline")
|
|
|
|
parser.add_argument("--detailed_times", action='store_true',
|
|
|
|
help="show cpu time details (split by user, system, child user, child system)")
|
|
|
|
return parser
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
args = get_arg_parser().parse_args(sys.argv[1:])
|
|
|
|
if args.list_all:
|
|
|
|
for p in psutil.process_iter():
|
|
|
|
print('cmdline', p.cmdline(), 'name', p.name())
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
if len(args.proc_names) > 0:
|
|
|
|
monitored_proc_names = args.proc_names.split(',')
|
|
|
|
monitored_procs = []
|
|
|
|
stats = {}
|
|
|
|
for p in psutil.process_iter():
|
|
|
|
if p == psutil.Process():
|
|
|
|
continue
|
|
|
|
matched = any([l for l in p.cmdline() if any([pn for pn in monitored_proc_names if re.match(r'.*{}.*'.format(pn), l, re.M | re.I)])])
|
|
|
|
if matched:
|
|
|
|
k = ' '.join(p.cmdline())
|
|
|
|
print('Add monitored proc:', k)
|
|
|
|
stats[k] = {'cpu_samples': defaultdict(list), 'min': defaultdict(lambda: None), 'max': defaultdict(lambda: None),
|
2020-05-31 13:37:52 -06:00
|
|
|
'avg': defaultdict(lambda: 0.0), 'last_cpu_times': None, 'last_sys_time': None}
|
2020-01-17 12:23:21 -07:00
|
|
|
stats[k]['last_sys_time'] = timer()
|
|
|
|
stats[k]['last_cpu_times'] = p.cpu_times()
|
|
|
|
monitored_procs.append(p)
|
|
|
|
i = 0
|
|
|
|
interval_int = int(PRINT_INTERVAL / SLEEP_INTERVAL)
|
|
|
|
while True:
|
|
|
|
for p in monitored_procs:
|
|
|
|
k = ' '.join(p.cmdline())
|
|
|
|
cur_sys_time = timer()
|
|
|
|
cur_cpu_times = p.cpu_times()
|
|
|
|
cpu_times = np.subtract(cur_cpu_times, stats[k]['last_cpu_times']) / (cur_sys_time - stats[k]['last_sys_time'])
|
|
|
|
stats[k]['last_sys_time'] = cur_sys_time
|
|
|
|
stats[k]['last_cpu_times'] = cur_cpu_times
|
|
|
|
cpu_percent = 0
|
|
|
|
for num, name in enumerate(cpu_time_names):
|
|
|
|
stats[k]['cpu_samples'][name].append(cpu_times[num])
|
|
|
|
cpu_percent += cpu_times[num]
|
|
|
|
stats[k]['cpu_samples']['total'].append(cpu_percent)
|
|
|
|
time.sleep(SLEEP_INTERVAL)
|
|
|
|
i += 1
|
|
|
|
if i % interval_int == 0:
|
|
|
|
l = []
|
|
|
|
for k, stat in stats.items():
|
|
|
|
if len(stat['cpu_samples']) <= 0:
|
|
|
|
continue
|
|
|
|
for name, samples in stat['cpu_samples'].items():
|
|
|
|
samples = np.array(samples)
|
|
|
|
avg = samples.mean()
|
|
|
|
c = samples.size
|
|
|
|
min_cpu = np.amin(samples)
|
|
|
|
max_cpu = np.amax(samples)
|
|
|
|
if stat['min'][name] is None or min_cpu < stat['min'][name]:
|
|
|
|
stat['min'][name] = min_cpu
|
|
|
|
if stat['max'][name] is None or max_cpu > stat['max'][name]:
|
|
|
|
stat['max'][name] = max_cpu
|
|
|
|
stat['avg'][name] = (stat['avg'][name] * (i - c) + avg * c) / (i)
|
|
|
|
stat['cpu_samples'][name] = []
|
|
|
|
|
|
|
|
msg = 'avg: {1:.2%}, min: {2:.2%}, max: {3:.2%} {0}'.format(os.path.basename(k), stat['avg']['total'], stat['min']['total'], stat['max']['total'])
|
|
|
|
if args.detailed_times:
|
|
|
|
for stat_type in ['avg', 'min', 'max']:
|
|
|
|
msg += '\n {}: {}'.format(stat_type, [name + ':' + str(round(stat[stat_type][name]*100, 2)) for name in cpu_time_names])
|
|
|
|
l.append((os.path.basename(k), stat['avg']['total'], msg))
|
2020-05-31 18:34:16 -06:00
|
|
|
l.sort(key=lambda x: -x[1])
|
2020-01-17 12:23:21 -07:00
|
|
|
for x in l:
|
|
|
|
print(x[2])
|
|
|
|
print('avg sum: {0:.2%} over {1} samples {2} seconds\n'.format(
|
|
|
|
sum([stat['avg']['total'] for k, stat in stats.items()]), i, i * SLEEP_INTERVAL
|
|
|
|
))
|