Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Unified Diff: tools/telemetry/telemetry/timeline/trace_event_importer.py

Issue 1647513002: Delete tools/telemetry. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/timeline/trace_event_importer.py
diff --git a/tools/telemetry/telemetry/timeline/trace_event_importer.py b/tools/telemetry/telemetry/timeline/trace_event_importer.py
deleted file mode 100644
index 2113f08c0ec1aa3c7b1d7ae143f11d29263ce62c..0000000000000000000000000000000000000000
--- a/tools/telemetry/telemetry/timeline/trace_event_importer.py
+++ /dev/null
@@ -1,448 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""TraceEventImporter imports TraceEvent-formatted data
-into the provided model.
-This is a port of the trace event importer from
-https://code.google.com/p/trace-viewer/
-"""
-
-import collections
-import copy
-
-import telemetry.timeline.async_slice as tracing_async_slice
-import telemetry.timeline.flow_event as tracing_flow_event
-from telemetry.timeline import importer
-from telemetry.timeline import memory_dump_event
-from telemetry.timeline import trace_data as trace_data_module
-
-
-class TraceEventTimelineImporter(importer.TimelineImporter):
- def __init__(self, model, trace_data):
- super(TraceEventTimelineImporter, self).__init__(
- model, trace_data, import_order=1)
- assert isinstance(trace_data, trace_data_module.TraceData)
- self._trace_data = trace_data
-
- self._all_async_events = []
- self._all_object_events = []
- self._all_flow_events = []
- self._all_memory_dumps_by_dump_id = collections.defaultdict(list)
-
- self._events = trace_data.GetEventsFor(trace_data_module.CHROME_TRACE_PART)
-
- @staticmethod
- def GetSupportedPart():
- return trace_data_module.CHROME_TRACE_PART
-
- def _GetOrCreateProcess(self, pid):
- return self._model.GetOrCreateProcess(pid)
-
- def _DeepCopyIfNeeded(self, obj):
- if self._trace_data.events_are_safely_mutable:
- return obj
- return copy.deepcopy(obj)
-
- def _ProcessAsyncEvent(self, event):
- """Helper to process an 'async finish' event, which will close an
- open slice.
- """
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- self._all_async_events.append({
- 'event': event,
- 'thread': thread})
-
- def _ProcessCounterEvent(self, event):
- """Helper that creates and adds samples to a Counter object based on
- 'C' phase events.
- """
- if 'id' in event:
- ctr_name = event['name'] + '[' + str(event['id']) + ']'
- else:
- ctr_name = event['name']
-
- ctr = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateCounter(event['cat'], ctr_name))
- # Initialize the counter's series fields if needed.
- if len(ctr.series_names) == 0:
- #TODO: implement counter object
- for series_name in event['args']:
- ctr.series_names.append(series_name)
- if len(ctr.series_names) == 0:
- self._model.import_errors.append('Expected counter ' + event['name'] +
- ' to have at least one argument to use as a value.')
- # Drop the counter.
- del ctr.parent.counters[ctr.full_name]
- return
-
- # Add the sample values.
- ctr.timestamps.append(event['ts'] / 1000.0)
- for series_name in ctr.series_names:
- if series_name not in event['args']:
- ctr.samples.append(0)
- continue
- ctr.samples.append(event['args'][series_name])
-
- def _ProcessObjectEvent(self, event):
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- self._all_object_events.append({
- 'event': event,
- 'thread': thread})
-
- def _ProcessDurationEvent(self, event):
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- if not thread.IsTimestampValidForBeginOrEnd(event['ts'] / 1000.0):
- self._model.import_errors.append(
- 'Timestamps are moving backward.')
- return
-
- if event['ph'] == 'B':
- thread.BeginSlice(event['cat'],
- event['name'],
- event['ts'] / 1000.0,
- event['tts'] / 1000.0 if 'tts' in event else None,
- event['args'])
- elif event['ph'] == 'E':
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- if not thread.IsTimestampValidForBeginOrEnd(event['ts'] / 1000.0):
- self._model.import_errors.append(
- 'Timestamps are moving backward.')
- return
- if not thread.open_slice_count:
- self._model.import_errors.append(
- 'E phase event without a matching B phase event.')
- return
-
- new_slice = thread.EndSlice(
- event['ts'] / 1000.0,
- event['tts'] / 1000.0 if 'tts' in event else None)
- for arg_name, arg_value in event.get('args', {}).iteritems():
- if arg_name in new_slice.args:
- self._model.import_errors.append(
- 'Both the B and E phases of ' + new_slice.name +
- ' provided values for argument ' + arg_name + '. ' +
- 'The value of the E phase event will be used.')
- new_slice.args[arg_name] = arg_value
-
- def _ProcessCompleteEvent(self, event):
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- thread.PushCompleteSlice(
- event['cat'],
- event['name'],
- event['ts'] / 1000.0,
- event['dur'] / 1000.0 if 'dur' in event else None,
- event['tts'] / 1000.0 if 'tts' in event else None,
- event['tdur'] / 1000.0 if 'tdur' in event else None,
- event['args'])
-
- def _ProcessMarkEvent(self, event):
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- thread.PushMarkSlice(
- event['cat'],
- event['name'],
- event['ts'] / 1000.0,
- event['tts'] / 1000.0 if 'tts' in event else None,
- event['args'] if 'args' in event else None)
-
- def _ProcessMetadataEvent(self, event):
- if event['name'] == 'thread_name':
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- thread.name = event['args']['name']
- elif event['name'] == 'process_name':
- process = self._GetOrCreateProcess(event['pid'])
- process.name = event['args']['name']
- elif event['name'] == 'process_labels':
- process = self._GetOrCreateProcess(event['pid'])
- process.labels = event['args']['labels']
- elif event['name'] == 'trace_buffer_overflowed':
- process = self._GetOrCreateProcess(event['pid'])
- process.SetTraceBufferOverflowTimestamp(event['args']['overflowed_at_ts'])
- else:
- self._model.import_errors.append(
- 'Unrecognized metadata name: ' + event['name'])
-
- def _ProcessInstantEvent(self, event):
- # Treat an Instant event as a duration 0 slice.
- # SliceTrack's redraw() knows how to handle this.
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- thread.BeginSlice(event['cat'],
- event['name'],
- event['ts'] / 1000.0,
- args=event.get('args'))
- thread.EndSlice(event['ts'] / 1000.0)
-
- def _ProcessSampleEvent(self, event):
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- thread.AddSample(event['cat'],
- event['name'],
- event['ts'] / 1000.0,
- event.get('args'))
-
- def _ProcessFlowEvent(self, event):
- thread = (self._GetOrCreateProcess(event['pid'])
- .GetOrCreateThread(event['tid']))
- self._all_flow_events.append({
- 'event': event,
- 'thread': thread})
-
- def _ProcessMemoryDumpEvents(self, events):
- # Dictionary to order dumps by id and process.
- global_dumps = {}
- for event in events:
- global_dump = global_dumps.setdefault(event['id'], {})
- dump_events = global_dump.setdefault(event['pid'], [])
- dump_events.append(event)
- for dump_id, global_dump in global_dumps.iteritems():
- for pid, dump_events in global_dump.iteritems():
- process = self._GetOrCreateProcess(pid)
- memory_dump = memory_dump_event.ProcessMemoryDumpEvent(process,
- dump_events)
- process.AddMemoryDumpEvent(memory_dump)
- self._all_memory_dumps_by_dump_id[dump_id].append(memory_dump)
-
- def ImportEvents(self):
- """Walks through the events_ list and outputs the structures discovered to
- model_.
- """
- memory_dump_events = []
- for event in self._events:
- phase = event.get('ph', None)
- if phase == 'B' or phase == 'E':
- self._ProcessDurationEvent(event)
- elif phase == 'X':
- self._ProcessCompleteEvent(event)
- # Note, S, F, T are deprecated and replaced by 'b' and 'e'. For
- # backwards compatibility continue to support them here.
- elif phase == 'S' or phase == 'F' or phase == 'T':
- self._ProcessAsyncEvent(event)
- elif phase == 'b' or phase == 'e':
- self._ProcessAsyncEvent(event)
- # Note, I is historic. The instant event marker got changed, but we
- # want to support loading old trace files so we have both I and i.
- elif phase == 'I' or phase == 'i':
- self._ProcessInstantEvent(event)
- elif phase == 'P':
- self._ProcessSampleEvent(event)
- elif phase == 'C':
- self._ProcessCounterEvent(event)
- elif phase == 'M':
- self._ProcessMetadataEvent(event)
- elif phase == 'N' or phase == 'D' or phase == 'O':
- self._ProcessObjectEvent(event)
- elif phase == 's' or phase == 't' or phase == 'f':
- self._ProcessFlowEvent(event)
- elif phase == 'v':
- memory_dump_events.append(event)
- elif phase == 'R':
- self._ProcessMarkEvent(event)
- else:
- self._model.import_errors.append('Unrecognized event phase: ' +
- phase + '(' + event['name'] + ')')
-
- # Memory dumps of a process with the same dump id need to be merged before
- # processing. So, memory dump events are processed all at once.
- self._ProcessMemoryDumpEvents(memory_dump_events)
- return self._model
-
- def FinalizeImport(self):
- """Called by the Model after all other importers have imported their
- events."""
- self._model.UpdateBounds()
-
- # We need to reupdate the bounds in case the minimum start time changes
- self._model.UpdateBounds()
- self._CreateAsyncSlices()
- self._CreateFlowSlices()
- self._SetBrowserProcess()
- self._SetGpuProcess()
- self._CreateExplicitObjects()
- self._CreateImplicitObjects()
- self._CreateMemoryDumps()
-
- def _CreateAsyncSlices(self):
- if len(self._all_async_events) == 0:
- return
-
- self._all_async_events.sort(key=lambda x: x['event']['ts'])
-
- async_event_states_by_name_then_id = {}
-
- all_async_events = self._all_async_events
- for async_event_state in all_async_events:
- event = async_event_state['event']
- name = event.get('name', None)
- if name is None:
- self._model.import_errors.append(
- 'Async events (ph: b, e, S, T or F) require an name parameter.')
- continue
-
- event_id = event.get('id')
- if event_id is None:
- self._model.import_errors.append(
- 'Async events (ph: b, e, S, T or F) require an id parameter.')
- continue
-
- # TODO(simonjam): Add a synchronous tick on the appropriate thread.
-
- if event['ph'] == 'S' or event['ph'] == 'b':
- if not name in async_event_states_by_name_then_id:
- async_event_states_by_name_then_id[name] = {}
- if event_id in async_event_states_by_name_then_id[name]:
- self._model.import_errors.append(
- 'At %d, a slice of the same id %s was already open.' % (
- event['ts'], event_id))
- continue
-
- async_event_states_by_name_then_id[name][event_id] = []
- async_event_states_by_name_then_id[name][event_id].append(
- async_event_state)
- else:
- if name not in async_event_states_by_name_then_id:
- self._model.import_errors.append(
- 'At %d, no slice named %s was open.' % (event['ts'], name,))
- continue
- if event_id not in async_event_states_by_name_then_id[name]:
- self._model.import_errors.append(
- 'At %d, no slice named %s with id=%s was open.' % (
- event['ts'], name, event_id))
- continue
- events = async_event_states_by_name_then_id[name][event_id]
- events.append(async_event_state)
-
- if event['ph'] == 'F' or event['ph'] == 'e':
- # Create a slice from start to end.
- async_slice = tracing_async_slice.AsyncSlice(
- events[0]['event']['cat'],
- name,
- events[0]['event']['ts'] / 1000.0)
-
- async_slice.duration = ((event['ts'] / 1000.0)
- - (events[0]['event']['ts'] / 1000.0))
-
- async_slice.start_thread = events[0]['thread']
- async_slice.end_thread = async_event_state['thread']
- if async_slice.start_thread == async_slice.end_thread:
- if 'tts' in event and 'tts' in events[0]['event']:
- async_slice.thread_start = events[0]['event']['tts'] / 1000.0
- async_slice.thread_duration = ((event['tts'] / 1000.0)
- - (events[0]['event']['tts'] / 1000.0))
- async_slice.id = event_id
- async_slice.args = events[0]['event']['args']
-
- # Create sub_slices for each step.
- for j in xrange(1, len(events)):
- sub_name = name
- if events[j - 1]['event']['ph'] == 'T':
- sub_name = name + ':' + events[j - 1]['event']['args']['step']
- sub_slice = tracing_async_slice.AsyncSlice(
- events[0]['event']['cat'],
- sub_name,
- events[j - 1]['event']['ts'] / 1000.0)
- sub_slice.parent_slice = async_slice
-
- sub_slice.duration = ((events[j]['event']['ts'] / 1000.0)
- - (events[j - 1]['event']['ts'] / 1000.0))
-
- sub_slice.start_thread = events[j - 1]['thread']
- sub_slice.end_thread = events[j]['thread']
- if sub_slice.start_thread == sub_slice.end_thread:
- if 'tts' in events[j]['event'] and \
- 'tts' in events[j - 1]['event']:
- sub_slice.thread_duration = \
- ((events[j]['event']['tts'] / 1000.0)
- - (events[j - 1]['event']['tts'] / 1000.0))
-
- sub_slice.id = event_id
- sub_slice.args = events[j - 1]['event']['args']
-
- async_slice.AddSubSlice(sub_slice)
-
- # The args for the finish event go in the last sub_slice.
- last_slice = async_slice.sub_slices[-1]
- for arg_name, arg_value in event['args'].iteritems():
- last_slice.args[arg_name] = arg_value
-
- # Add |async_slice| to the start-thread's async_slices.
- async_slice.start_thread.AddAsyncSlice(async_slice)
- del async_event_states_by_name_then_id[name][event_id]
-
- def _CreateExplicitObjects(self):
- # TODO(tengs): Implement object instance parsing
- pass
-
- def _CreateImplicitObjects(self):
- # TODO(tengs): Implement object instance parsing
- pass
-
- def _CreateFlowSlices(self):
- if len(self._all_flow_events) == 0:
- return
-
- self._all_flow_events.sort(key=lambda x: x['event']['ts'])
-
- flow_id_to_event = {}
- for data in self._all_flow_events:
- event = data['event']
- thread = data['thread']
- if 'name' not in event:
- self._model.import_errors.append(
- 'Flow events (ph: s, t or f) require a name parameter.')
- continue
- if 'id' not in event:
- self._model.import_errors.append(
- 'Flow events (ph: s, t or f) require an id parameter.')
- continue
-
- flow_event = tracing_flow_event.FlowEvent(
- event['cat'],
- event['id'],
- event['name'],
- event['ts'] / 1000.0,
- event['args'])
- thread.AddFlowEvent(flow_event)
-
- if event['ph'] == 's':
- if event['id'] in flow_id_to_event:
- self._model.import_errors.append(
- 'event id %s already seen when encountering start of'
- 'flow event.' % event['id'])
- continue
- flow_id_to_event[event['id']] = flow_event
- elif event['ph'] == 't' or event['ph'] == 'f':
- if not event['id'] in flow_id_to_event:
- self._model.import_errors.append(
- 'Found flow phase %s for id: %s but no flow start found.' % (
- event['ph'], event['id']))
- continue
- flow_position = flow_id_to_event[event['id']]
- self._model.flow_events.append([flow_position, flow_event])
-
- if event['ph'] == 'f':
- del flow_id_to_event[event['id']]
- else:
- # Make this event the next start event in this flow.
- flow_id_to_event[event['id']] = flow_event
-
- def _CreateMemoryDumps(self):
- self._model.SetGlobalMemoryDumps(
- memory_dump_event.GlobalMemoryDump(events)
- for events in self._all_memory_dumps_by_dump_id.itervalues())
-
- def _SetBrowserProcess(self):
- for thread in self._model.GetAllThreads():
- if thread.name == 'CrBrowserMain':
- self._model.browser_process = thread.parent
-
- def _SetGpuProcess(self):
- for thread in self._model.GetAllThreads():
- if thread.name == 'CrGpuMain':
- self._model.gpu_process = thread.parent

Powered by Google App Engine
This is Rietveld 408576698