test onroad: more robust CPU usage test (#25375)

* test onroad: more robust CPU usage test

* fix linter

* remove debug print

* Revert "remove debug print"

This reverts commit 172cb655fe.

Co-authored-by: Comma Device <device@comma.ai>
pull/25376/head
Adeeb Shihadeh 3 years ago committed by GitHub
parent 088719c86c
commit 80cbcafb5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      selfdrive/test/test_onroad.py

@ -5,7 +5,7 @@ import subprocess
import time import time
import numpy as np import numpy as np
import unittest import unittest
from collections import Counter from collections import Counter, defaultdict
from pathlib import Path from pathlib import Path
from cereal import car from cereal import car
@ -70,32 +70,40 @@ def cputime_total(ct):
return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem
def check_cpu_usage(first_proc, last_proc): def check_cpu_usage(proclogs):
result = "\n" result = "\n"
result += "------------------------------------------------\n" result += "------------------------------------------------\n"
result += "------------------ CPU Usage -------------------\n" result += "------------------ CPU Usage -------------------\n"
result += "------------------------------------------------\n" result += "------------------------------------------------\n"
plogs_by_proc = defaultdict(list)
for pl in proclogs:
for x in pl.procLog.procs:
if len(x.cmdline) > 0:
n = list(x.cmdline)[0]
plogs_by_proc[n].append(x)
print(plogs_by_proc.keys())
r = True r = True
dt = (last_proc.logMonoTime - first_proc.logMonoTime) / 1e9 dt = (proclogs[-1].logMonoTime - proclogs[0].logMonoTime) / 1e9
for proc_name, normal_cpu_usage in PROCS.items(): for proc_name, expected_cpu in PROCS.items():
err = "" err = ""
first, last = None, None cpu_usage = 0.
try: x = plogs_by_proc[proc_name]
first = [p for p in first_proc.procLog.procs if proc_name in p.cmdline][0] if len(x) > 2:
last = [p for p in last_proc.procLog.procs if proc_name in p.cmdline][0] cpu_time = cputime_total(x[-1]) - cputime_total(x[0])
cpu_time = cputime_total(last) - cputime_total(first)
cpu_usage = cpu_time / dt * 100. cpu_usage = cpu_time / dt * 100.
if cpu_usage > max(normal_cpu_usage * 1.15, normal_cpu_usage + 5.0): if cpu_usage > max(expected_cpu * 1.15, expected_cpu + 5.0):
# cpu usage is high while playing sounds # cpu usage is high while playing sounds
if not (proc_name == "./_soundd" and cpu_usage < 65.): if not (proc_name == "./_soundd" and cpu_usage < 65.):
err = "using more CPU than normal" err = "using more CPU than normal"
elif cpu_usage < min(normal_cpu_usage * 0.65, max(normal_cpu_usage - 1.0, 0.0)): elif cpu_usage < min(expected_cpu * 0.65, max(expected_cpu - 1.0, 0.0)):
err = "using less CPU than normal" err = "using less CPU than normal"
except IndexError: else:
err = f"NO METRICS FOUND {first=} {last=}\n" err = "NO METRICS FOUND"
result += f"{proc_name.ljust(35)} {cpu_usage:5.2f}% ({normal_cpu_usage:5.2f}%) {err}\n" result += f"{proc_name.ljust(35)} {cpu_usage:5.2f}% ({expected_cpu:5.2f}%) {err}\n"
if len(err) > 0: if len(err) > 0:
r = False r = False
@ -111,6 +119,7 @@ class TestOnroad(unittest.TestCase):
if "DEBUG" in os.environ: if "DEBUG" in os.environ:
segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog")), Path(ROOT).iterdir()) segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog")), Path(ROOT).iterdir())
segs = sorted(segs, key=lambda x: x.stat().st_mtime) segs = sorted(segs, key=lambda x: x.stat().st_mtime)
print(segs[-1])
cls.lr = list(LogReader(os.path.join(segs[-1], "rlog"))) cls.lr = list(LogReader(os.path.join(segs[-1], "rlog")))
return return
@ -180,7 +189,7 @@ class TestOnroad(unittest.TestCase):
def test_cpu_usage(self): def test_cpu_usage(self):
proclogs = [m for m in self.lr if m.which() == 'procLog'] proclogs = [m for m in self.lr if m.which() == 'procLog']
self.assertGreater(len(proclogs), service_list['procLog'].frequency * 45, "insufficient samples") self.assertGreater(len(proclogs), service_list['procLog'].frequency * 45, "insufficient samples")
cpu_ok = check_cpu_usage(proclogs[0], proclogs[-1]) cpu_ok = check_cpu_usage(proclogs)
self.assertTrue(cpu_ok) self.assertTrue(cpu_ok)
def test_camera_processing_time(self): def test_camera_processing_time(self):

Loading…
Cancel
Save