in python/profilo/importer/interpreter.py [0:0]
def interpret(self):
self.parents, self.children = self.__calculate_parents_children()
self.trace = Trace(
begin=min(
(
x.timestamp
for x in self.trace_file.entries
if hasattr(x, "timestamp")
)
),
end=max(
(
x.timestamp
for x in self.trace_file.entries
if hasattr(x, "timestamp")
)
),
id=self.trace_file.headers.get("id"),
)
thread_items = {}
framework_frames = {} # method_id -> full name
for entry in self.trace_file.entries:
if entry.type == "JAVA_FRAME_NAME":
for child in self.children[entry]:
framework_frames[entry.arg3] = child.data
continue
if isinstance(entry, StandardEntry):
thread_items.setdefault(entry.tid, []).append(entry)
# BytesEntries will be processed as children of the above.
BLOCK_START_ENTRIES = ["MARK_PUSH", "IO_START", "BINDER_START"]
BLOCK_END_ENTRIES = ["MARK_POP", "IO_END", "BINDER_END"]
THREAD_METADATA_ENTRIES = ["TRACE_THREAD_NAME", "TRACE_THREAD_PRI"]
for tid, items in thread_items.items():
entries = list(sorted(items, key=cmp_to_key(entry_compare)))
unit = self.ensure_unit(tid)
stacks = {} # timestamp -> [addresses]
# First, build blocks.
for entry in entries:
block = None
if entry.type in BLOCK_START_ENTRIES:
block = unit.push_block(entry.timestamp)
self.block_entries.setdefault(block, BlockEntries()).begin = entry
elif entry.type in BLOCK_END_ENTRIES:
block = unit.pop_block(entry.timestamp)
self.block_entries.setdefault(block, BlockEntries()).end = entry
elif entry.type == "STACK_FRAME":
# While we're here, build the stack trace maps.
stacks.setdefault(entry.timestamp, []).append(entry.arg3)
elif entry.type in THREAD_METADATA_ENTRIES:
self.process_thread_metadata(entry)
if block:
block_entries = self.block_entries[block]
self.assign_name(
block,
entries=[
block_entries.begin,
block_entries.end,
],
)
unit.normalize_blocks()
"""Attach single points. We can't do this as part of the
block-building pass due to this edge case of unbalanced pops:
PUSH(1) POP(2) COUNTER(3) POP(4)
We want this to create the following:
[ (3) (4)]
[(1) (2)]
This is impossible to achieve in a single pass because we can't
create the block ending in (4) at the time we visit (3).
"""
for entry in entries:
if entry.type == "COUNTER":
item = unit.add_point(entry.timestamp)
item.properties.add_counter(
name=COUNTER_NAMES[entry.arg1],
value=entry.arg3,
)
self.assign_name(item, entries=[entry])
elif entry.type == "STACK_FRAME":
if entry.timestamp in stacks:
# we haven't written this stack trace yet, proceed
item = unit.add_point(entry.timestamp)
self.assign_name(item, entries=[entry])
stacktrace = StackTrace()
for frame in stacks[entry.timestamp]:
symbol = None
if self.symbols:
symbol = self.symbols.method_index.get(frame, None)
if symbol is None:
# Let's see if it's a framework frame
symbol = framework_frames.get(frame, None)
stacktrace.append(identifier=frame, symbol=symbol)
item.properties.stackTraces.update(
{
"stacks": stacktrace,
}
)
# clear the entry in the map so we don't add a point
# for every frame
del stacks[entry.timestamp]
pass
return self.trace