1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import telemetry.timeline.event as timeline_event
6
7
8class Slice(timeline_event.TimelineEvent):
9  """A Slice represents an interval of time plus parameters associated
10  with that interval.
11
12  NOTE: The Sample class implements the same interface as
13  Slice. These must be kept in sync.
14
15  All time units are stored in milliseconds.
16  """
17  def __init__(self, parent_thread, category, name, timestamp, duration=0,
18               thread_timestamp=None, thread_duration=None, args=None):
19    super(Slice, self).__init__(
20        category, name, timestamp, duration, thread_timestamp, thread_duration,
21        args)
22    self.parent_thread = parent_thread
23    self.parent_slice = None
24    self.sub_slices = []
25    self.did_not_finish = False
26
27  def AddSubSlice(self, sub_slice):
28    assert sub_slice.parent_slice == self
29    self.sub_slices.append(sub_slice)
30
31  def IterEventsInThisContainerRecrusively(self, stack=None):
32    # This looks awkward, but it lets us create only a single iterator instead
33    # of having to create one iterator for every subslice found.
34    if stack == None:
35      stack = []
36    else:
37      assert len(stack) == 0
38    stack.extend(reversed(self.sub_slices))
39    while len(stack):
40      s = stack.pop()
41      yield s
42      stack.extend(reversed(s.sub_slices))
43
44  @property
45  def self_time(self):
46    """Time spent in this function less any time spent in child events."""
47    child_total = sum(
48      [e.duration for e in self.sub_slices])
49    return self.duration - child_total
50
51  @property
52  def self_thread_time(self):
53    """Thread (scheduled) time spent in this function less any thread time spent
54    in child events. Returns None if the slice or any of its children does not
55    have a thread_duration value.
56    """
57    if not self.thread_duration:
58      return None
59
60    child_total = 0
61    for e in self.sub_slices:
62      if e.thread_duration == None:
63        return None
64      child_total += e.thread_duration
65
66    return self.thread_duration - child_total
67
68  def _GetSubSlicesRecursive(self):
69    for sub_slice in self.sub_slices:
70      for s in sub_slice.GetAllSubSlices():
71        yield s
72      yield sub_slice
73
74  def GetAllSubSlices(self):
75    return list(self._GetSubSlicesRecursive())
76
77  def GetAllSubSlicesOfName(self, name):
78    return [e for e in self.GetAllSubSlices() if e.name == name]
79