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