Files
sunnypilot/selfdrive/test/profiling/profiler.py

98 lines
2.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import os
import sys
import cProfile
import pprofile
import pyprof2calltree
from opendbc.car.toyota.values import CAR as TOYOTA
from opendbc.car.honda.values import CAR as HONDA
from opendbc.car.volkswagen.values import CAR as VW
from openpilot.common.params import Params
from openpilot.tools.lib.logreader import LogReader
from openpilot.selfdrive.test.profiling.lib import SubMaster, PubMaster, SubSocket, ReplayDone
from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS
BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/"
CARS = {
'toyota': ("0982d79ebb0de295|2021-01-03--20-03-36/6", TOYOTA.TOYOTA_RAV4),
'honda': ("0982d79ebb0de295|2021-01-08--10-13-10/6", HONDA.HONDA_CIVIC),
"vw": ("ef895f46af5fd73f|2021-05-22--14-06-35/6", VW.AUDI_A3_MK3),
}
def get_inputs(msgs, process, fingerprint):
for config in CONFIGS:
if config.proc_name == process:
sub_socks = list(config.pubs)
trigger = sub_socks[0]
break
# some procs block on CarParams
for msg in msgs:
if msg.which() == 'carParams':
m = msg.as_builder()
m.carParams.carFingerprint = fingerprint
Params().put("CarParams", m.carParams.copy().to_bytes())
break
sm = SubMaster(msgs, trigger, sub_socks)
pm = PubMaster()
if 'can' in sub_socks:
can_sock = SubSocket(msgs, 'can')
else:
can_sock = None
return sm, pm, can_sock
def profile(proc, func, car='toyota'):
segment, fingerprint = CARS[car]
segment = segment.replace('|', '/')
rlog_url = f"{BASE_URL}{segment}/rlog.bz2"
msgs = list(LogReader(rlog_url)) * int(os.getenv("LOOP", "1"))
os.environ['FINGERPRINT'] = fingerprint
os.environ['SKIP_FW_QUERY'] = "1"
os.environ['REPLAY'] = "1"
def run(sm, pm, can_sock):
try:
if can_sock is not None:
func(sm, pm, can_sock)
else:
func(sm, pm)
except ReplayDone:
pass
# Statistical
sm, pm, can_sock = get_inputs(msgs, proc, fingerprint)
with pprofile.StatisticalProfile()(period=0.00001) as pr:
run(sm, pm, can_sock)
pr.dump_stats(f'cachegrind.out.{proc}_statistical')
# Deterministic
sm, pm, can_sock = get_inputs(msgs, proc, fingerprint)
with cProfile.Profile() as pr:
run(sm, pm, can_sock)
pyprof2calltree.convert(pr.getstats(), f'cachegrind.out.{proc}_deterministic')
if __name__ == '__main__':
from openpilot.selfdrive.controls.controlsd import main as controlsd_thread
from openpilot.selfdrive.locationd.paramsd import main as paramsd_thread
from openpilot.selfdrive.controls.plannerd import main as plannerd_thread
procs = {
'controlsd': controlsd_thread,
'paramsd': paramsd_thread,
'plannerd': plannerd_thread,
}
proc = sys.argv[1]
if proc not in procs:
print(f"{proc} not available")
sys.exit(0)
else:
profile(proc, procs[proc])