• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1""" NNAPI systrace parser - getting data in from a systrace html output """
2
3import re
4import sys
5
6def get_trace_part(filename):
7  """ Finds the text trace in the given html file, returns as a string. """
8  with open(filename) as f:
9    lines = f.readlines()
10  seen_begin = False
11  trace = []
12  lineno = 0
13  for line in lines:
14    lineno = lineno + 1
15    if ("#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION" in line or
16        "#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION" in line):
17      seen_begin = True
18    if seen_begin:
19      if "</script>" in line:
20        break
21      trace.append([line, lineno])
22  return trace
23
24MATCHER = re.compile(r"^\s*([^ ].{1,15})-(\d+)\s+\(\s*([-0-9]+)\) .* (\d+\.\d+): tracing_mark_write: ([BE].*)$")
25MATCHER_FOR_OLD = re.compile(r"^\s*([^ ].{1,15})-(\d+) .* (\d+\.\d+): tracing_mark_write: ([BE].*)$")
26
27def parse_trace_part(trace):
28  """ Takes a string containing the text trace form systrace, parses the rows
29      and selects which threads we are interested in.
30
31      Returns (tracked_pids, driver_tgids, parsed), where:
32         - tracked_pids: map from pids we are interested in to their tgids
33         - driver_tgids: map that contains tgids of NNAPI driver processes
34         - parsed: list of parsed rows, each containing
35              TASK, PID, TGID, TIMESTAMP and FUNCTION
36           as shown below
37  """
38  # Row format
39  #  #           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION" in line:
40  #  #              | |        |      |   ||||       |         |
41  #    NeuralNetworks-5143  ( 5143) [005] ...1   142.924145: tracing_mark_write: B|5143|[NN_L
42  #  <...>-5149 ( 774) [000] ...1   143.103773: tracing_mark_write: B|774|[NN_LDV_PC][validat
43  #  <...>-756 ( 756) [000] ...1   143.140553: tracing_mark_write: B|756|HIDL::IDevice::prepa
44  #  <...>-5149  (-----) [001] ...1   143.149856: tracing_mark_write: B|756|[NN_LCC_PE][optim
45  #    HwBinder:784_1-5236  (  784) [001] ...1   397.528915: tracing_mark_write: B|784|HIDL::
46  #    GLThread 35-1739  ( 1500) [001] ...1   277.001798: tracing_mark_write: B|1500|HIDL::IMapper::importBuffer::passthrough
47  # Notes:
48  #    - systrace enter/exit marks are per PID, which is really a thread id on Linux
49  #    - TGIDs identify processes
50  #
51  mark_matcher = re.compile(r"([BE])\|(\d+).*")
52  tracked_pids = {}
53  driver_tgids = {}
54  pid_to_tgid = {}
55  parsed = []
56  seen_nnapi_runtime = False
57  for [line, lineno] in trace:
58    m = MATCHER.match(line)
59    m_old = MATCHER_FOR_OLD.match(line)
60    if not m and not m_old:
61      # Check parsing doesn't discard interesting lines
62      assert not "HIDL::IDevice" in line, line
63      assert not "[NN_" in line, line
64      assert not "tracing_mark_write: B" in line, line
65      assert not "tracing_mark_write: E" in line, line
66      continue
67    if m:
68      [task, pid, tgid, time, mark] = m.groups()
69    else:
70      [task, pid, time, mark] = m_old.groups()
71      if "|" in mark:
72        tgid = mark.split("|")[1]
73      else:
74        tgid = pid_to_tgid[pid]
75    assert pid
76    pid_to_tgid[pid] = tgid
77    if tgid == "-----":
78      mm = mark_matcher.match(mark)
79      tgid = mm.group(2)
80      assert tgid
81    parsed.append( [task, pid, tgid, time, mark, line, lineno] )
82    if "[NN" in mark:
83      tracked_pids[pid] = tgid
84      if "NN_LR" in mark:
85        seen_nnapi_runtime = True
86    if "HIDL::IDevice" in mark and "::server" in mark:
87      tracked_pids[pid] = tgid
88      driver_tgids[tgid] = True
89
90  if not seen_nnapi_runtime:
91    sys.stderr.write("\n*** No NNAPI Runtime trace present - check your systrace setup ***\n\n")
92  return tracked_pids, driver_tgids, parsed
93
94