| Index: tools/telemetry/telemetry/core/timeline/model.py
|
| diff --git a/tools/telemetry/telemetry/core/timeline/model.py b/tools/telemetry/telemetry/core/timeline/model.py
|
| deleted file mode 100644
|
| index 00b0f87a4a5616028f78424dc48278217e8dc045..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/telemetry/core/timeline/model.py
|
| +++ /dev/null
|
| @@ -1,247 +0,0 @@
|
| -# Copyright 2013 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.
|
| -'''A container for timeline-based events and traces and can handle importing
|
| -raw event data from different sources. This model closely resembles that in the
|
| -trace_viewer project:
|
| -https://code.google.com/p/trace-viewer/
|
| -'''
|
| -
|
| -from operator import attrgetter
|
| -
|
| -import telemetry.core.timeline.process as tracing_process
|
| -
|
| -# Register importers for data
|
| -from telemetry.core.timeline import bounds
|
| -from telemetry.core.timeline import empty_timeline_data_importer
|
| -from telemetry.core.timeline import inspector_importer
|
| -from telemetry.core.timeline import trace_event_importer
|
| -
|
| -_IMPORTERS = [
|
| - empty_timeline_data_importer.EmptyTimelineDataImporter,
|
| - inspector_importer.InspectorTimelineImporter,
|
| - trace_event_importer.TraceEventTimelineImporter
|
| -]
|
| -
|
| -
|
| -class MarkerMismatchError(Exception):
|
| - def __init__(self):
|
| - super(MarkerMismatchError, self).__init__(
|
| - 'Number or order of timeline markers does not match provided labels')
|
| -
|
| -
|
| -class MarkerOverlapError(Exception):
|
| - def __init__(self):
|
| - super(MarkerOverlapError, self).__init__(
|
| - 'Overlapping timeline markers found')
|
| -
|
| -
|
| -class TimelineModel(object):
|
| - def __init__(self, timeline_data=None, shift_world_to_zero=True):
|
| - """ Initializes a TimelineModel. timeline_data can be a single TimelineData
|
| - object, a list of TimelineData objects, or None. If timeline_data is not
|
| - None, all events from it will be imported into the model. The events will
|
| - be shifted such that the first event starts at time 0, if
|
| - shift_world_to_zero is True.
|
| - """
|
| - self._bounds = bounds.Bounds()
|
| - self._thread_time_bounds = {}
|
| - self._processes = {}
|
| - self._browser_process = None
|
| - self._frozen = False
|
| - self._tab_ids_to_renderer_threads_map = {}
|
| - self.import_errors = []
|
| - self.metadata = []
|
| - self.flow_events = []
|
| - if timeline_data is not None:
|
| - self.ImportTraces(timeline_data, shift_world_to_zero=shift_world_to_zero)
|
| -
|
| - @property
|
| - def bounds(self):
|
| - return self._bounds
|
| -
|
| - @property
|
| - def thread_time_bounds(self):
|
| - return self._thread_time_bounds
|
| -
|
| - @property
|
| - def processes(self):
|
| - return self._processes
|
| -
|
| - @property
|
| - #pylint: disable=E0202
|
| - def browser_process(self):
|
| - return self._browser_process
|
| -
|
| - @browser_process.setter
|
| - #pylint: disable=E0202
|
| - def browser_process(self, browser_process):
|
| - self._browser_process = browser_process
|
| -
|
| - def AddMappingFromTabIdToRendererThread(self, tab_id, renderer_thread):
|
| - if self._frozen:
|
| - raise Exception('Cannot add mapping from tab id to renderer thread once '
|
| - 'trace is imported')
|
| - self._tab_ids_to_renderer_threads_map[tab_id] = renderer_thread
|
| -
|
| - def ImportTraces(self, timeline_data, shift_world_to_zero=True):
|
| - if self._frozen:
|
| - raise Exception("Cannot add events once trace is imported")
|
| -
|
| - importers = []
|
| - if isinstance(timeline_data, list):
|
| - for item in timeline_data:
|
| - importers.append(self._CreateImporter(item))
|
| - else:
|
| - importers.append(self._CreateImporter(timeline_data))
|
| -
|
| - importers.sort(cmp=lambda x, y: x.import_priority - y.import_priority)
|
| -
|
| - for importer in importers:
|
| - # TODO: catch exceptions here and add it to error list
|
| - importer.ImportEvents()
|
| - self.FinalizeImport(shift_world_to_zero, importers)
|
| -
|
| - def FinalizeImport(self, shift_world_to_zero=False, importers=None):
|
| - if importers == None:
|
| - importers = []
|
| - self.UpdateBounds()
|
| - if not self.bounds.is_empty:
|
| - for process in self._processes.itervalues():
|
| - process.AutoCloseOpenSlices(self.bounds.max,
|
| - self.thread_time_bounds)
|
| -
|
| - for importer in importers:
|
| - importer.FinalizeImport()
|
| -
|
| - for process in self.processes.itervalues():
|
| - process.FinalizeImport()
|
| -
|
| - if shift_world_to_zero:
|
| - self.ShiftWorldToZero()
|
| - self.UpdateBounds()
|
| -
|
| - # Because of FinalizeImport, it would probably be a good idea
|
| - # to prevent the timeline from from being modified.
|
| - self._frozen = True
|
| -
|
| - def ShiftWorldToZero(self):
|
| - self.UpdateBounds()
|
| - if self._bounds.is_empty:
|
| - return
|
| - shift_amount = self._bounds.min
|
| - for event in self.IterAllEvents():
|
| - event.start -= shift_amount
|
| -
|
| - def UpdateBounds(self):
|
| - self._bounds.Reset()
|
| - for event in self.IterAllEvents():
|
| - self._bounds.AddValue(event.start)
|
| - self._bounds.AddValue(event.end)
|
| -
|
| - self._thread_time_bounds = {}
|
| - for thread in self.GetAllThreads():
|
| - self._thread_time_bounds[thread] = bounds.Bounds()
|
| - for event in thread.IterEventsInThisContainer():
|
| - if event.thread_start != None:
|
| - self._thread_time_bounds[thread].AddValue(event.thread_start)
|
| - if event.thread_end != None:
|
| - self._thread_time_bounds[thread].AddValue(event.thread_end)
|
| -
|
| - def GetAllContainers(self):
|
| - containers = []
|
| - def Iter(container):
|
| - containers.append(container)
|
| - for container in container.IterChildContainers():
|
| - Iter(container)
|
| - for process in self._processes.itervalues():
|
| - Iter(process)
|
| - return containers
|
| -
|
| - def IterAllEvents(self):
|
| - for container in self.GetAllContainers():
|
| - for event in container.IterEventsInThisContainer():
|
| - yield event
|
| -
|
| - def GetAllProcesses(self):
|
| - return self._processes.values()
|
| -
|
| - def GetAllThreads(self):
|
| - threads = []
|
| - for process in self._processes.values():
|
| - threads.extend(process.threads.values())
|
| - return threads
|
| -
|
| - def GetAllEvents(self):
|
| - return list(self.IterAllEvents())
|
| -
|
| - def GetAllEventsOfName(self, name, only_root_events=False):
|
| - events = [e for e in self.IterAllEvents() if e.name == name]
|
| - if only_root_events:
|
| - return filter(lambda ev: ev.parent_slice == None, events)
|
| - else:
|
| - return events
|
| -
|
| - def GetEventOfName(self, name, only_root_events=False,
|
| - fail_if_more_than_one=False):
|
| - events = self.GetAllEventsOfName(name, only_root_events)
|
| - if len(events) == 0:
|
| - raise Exception('No event of name "%s" found.' % name)
|
| - if fail_if_more_than_one and len(events) > 1:
|
| - raise Exception('More than one event of name "%s" found.' % name)
|
| - return events[0]
|
| -
|
| - def GetOrCreateProcess(self, pid):
|
| - if pid not in self._processes:
|
| - assert not self._frozen
|
| - self._processes[pid] = tracing_process.Process(self, pid)
|
| - return self._processes[pid]
|
| -
|
| - def FindTimelineMarkers(self, timeline_marker_names):
|
| - """Find the timeline events with the given names.
|
| -
|
| - If the number and order of events found does not match the names,
|
| - raise an error.
|
| - """
|
| - # Make sure names are in a list and remove all None names
|
| - if not isinstance(timeline_marker_names, list):
|
| - timeline_marker_names = [timeline_marker_names]
|
| - names = [x for x in timeline_marker_names if x is not None]
|
| -
|
| - # Gather all events that match the names and sort them.
|
| - events = []
|
| - name_set = set()
|
| - for name in names:
|
| - name_set.add(name)
|
| - for name in name_set:
|
| - events.extend(self.GetAllEventsOfName(name, True))
|
| - events.sort(key=attrgetter('start'))
|
| -
|
| - # Check if the number and order of events matches the provided names,
|
| - # and that the events don't overlap.
|
| - if len(events) != len(names):
|
| - raise MarkerMismatchError()
|
| - for (i, event) in enumerate(events):
|
| - if event.name != names[i]:
|
| - raise MarkerMismatchError()
|
| - for i in xrange(0, len(events)):
|
| - for j in xrange(i+1, len(events)):
|
| - if (events[j].start < events[i].start + events[i].duration):
|
| - raise MarkerOverlapError()
|
| -
|
| - return events
|
| -
|
| - def GetRendererProcessFromTabId(self, tab_id):
|
| - renderer_thread = self.GetRendererThreadFromTabId(tab_id)
|
| - if renderer_thread:
|
| - return renderer_thread.parent
|
| - return None
|
| -
|
| - def GetRendererThreadFromTabId(self, tab_id):
|
| - return self._tab_ids_to_renderer_threads_map.get(tab_id, None)
|
| -
|
| - def _CreateImporter(self, event_data):
|
| - for importer_class in _IMPORTERS:
|
| - if importer_class.CanImport(event_data):
|
| - return importer_class(self, event_data)
|
| - raise ValueError("Could not find an importer for the provided event data")
|
|
|