94 lines
3.6 KiB
Python
94 lines
3.6 KiB
Python
""" NNAPI systrace parser - getting data in from a systrace html output """
|
|
|
|
import re
|
|
import sys
|
|
|
|
def get_trace_part(filename):
|
|
""" Finds the text trace in the given html file, returns as a string. """
|
|
with open(filename) as f:
|
|
lines = f.readlines()
|
|
seen_begin = False
|
|
trace = []
|
|
lineno = 0
|
|
for line in lines:
|
|
lineno = lineno + 1
|
|
if ("# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION" in line or
|
|
"# TASK-PID CPU# |||| TIMESTAMP FUNCTION" in line):
|
|
seen_begin = True
|
|
if seen_begin:
|
|
if "</script>" in line:
|
|
break
|
|
trace.append([line, lineno])
|
|
return trace
|
|
|
|
MATCHER = re.compile(r"^\s*([^ ].{1,15})-(\d+)\s+\(\s*([-0-9]+)\) .* (\d+\.\d+): tracing_mark_write: ([BE].*)$")
|
|
MATCHER_FOR_OLD = re.compile(r"^\s*([^ ].{1,15})-(\d+) .* (\d+\.\d+): tracing_mark_write: ([BE].*)$")
|
|
|
|
def parse_trace_part(trace):
|
|
""" Takes a string containing the text trace form systrace, parses the rows
|
|
and selects which threads we are interested in.
|
|
|
|
Returns (tracked_pids, driver_tgids, parsed), where:
|
|
- tracked_pids: map from pids we are interested in to their tgids
|
|
- driver_tgids: map that contains tgids of NNAPI driver processes
|
|
- parsed: list of parsed rows, each containing
|
|
TASK, PID, TGID, TIMESTAMP and FUNCTION
|
|
as shown below
|
|
"""
|
|
# Row format
|
|
# # TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION" in line:
|
|
# # | | | | |||| | |
|
|
# NeuralNetworks-5143 ( 5143) [005] ...1 142.924145: tracing_mark_write: B|5143|[NN_L
|
|
# <...>-5149 ( 774) [000] ...1 143.103773: tracing_mark_write: B|774|[NN_LDV_PC][validat
|
|
# <...>-756 ( 756) [000] ...1 143.140553: tracing_mark_write: B|756|HIDL::IDevice::prepa
|
|
# <...>-5149 (-----) [001] ...1 143.149856: tracing_mark_write: B|756|[NN_LCC_PE][optim
|
|
# HwBinder:784_1-5236 ( 784) [001] ...1 397.528915: tracing_mark_write: B|784|HIDL::
|
|
# GLThread 35-1739 ( 1500) [001] ...1 277.001798: tracing_mark_write: B|1500|HIDL::IMapper::importBuffer::passthrough
|
|
# Notes:
|
|
# - systrace enter/exit marks are per PID, which is really a thread id on Linux
|
|
# - TGIDs identify processes
|
|
#
|
|
mark_matcher = re.compile(r"([BE])\|(\d+).*")
|
|
tracked_pids = {}
|
|
driver_tgids = {}
|
|
pid_to_tgid = {}
|
|
parsed = []
|
|
seen_nnapi_runtime = False
|
|
for [line, lineno] in trace:
|
|
m = MATCHER.match(line)
|
|
m_old = MATCHER_FOR_OLD.match(line)
|
|
if not m and not m_old:
|
|
# Check parsing doesn't discard interesting lines
|
|
assert not "HIDL::IDevice" in line, line
|
|
assert not "[NN_" in line, line
|
|
assert not "tracing_mark_write: B" in line, line
|
|
assert not "tracing_mark_write: E" in line, line
|
|
continue
|
|
if m:
|
|
[task, pid, tgid, time, mark] = m.groups()
|
|
else:
|
|
[task, pid, time, mark] = m_old.groups()
|
|
if "|" in mark:
|
|
tgid = mark.split("|")[1]
|
|
else:
|
|
tgid = pid_to_tgid[pid]
|
|
assert pid
|
|
pid_to_tgid[pid] = tgid
|
|
if tgid == "-----":
|
|
mm = mark_matcher.match(mark)
|
|
tgid = mm.group(2)
|
|
assert tgid
|
|
parsed.append( [task, pid, tgid, time, mark, line, lineno] )
|
|
if "[NN" in mark:
|
|
tracked_pids[pid] = tgid
|
|
if "NN_LR" in mark:
|
|
seen_nnapi_runtime = True
|
|
if "HIDL::IDevice" in mark and "::server" in mark:
|
|
tracked_pids[pid] = tgid
|
|
driver_tgids[tgid] = True
|
|
|
|
if not seen_nnapi_runtime:
|
|
sys.stderr.write("\n*** No NNAPI Runtime trace present - check your systrace setup ***\n\n")
|
|
return tracked_pids, driver_tgids, parsed
|
|
|