1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import telemetry.timeline.event_container as event_container
6a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
8a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch# Doesn't inherit from TimelineEvent because its only a temporary wrapper of a
9a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch# counter sample into an event. During stable operation, the samples are stored
10a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch# a dense array of values rather than in the long-form done by an Event.
11a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass CounterSample(object):
12a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def __init__(self, counter, sample_index):
13a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self._counter = counter
14a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self._sample_index = sample_index
15a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
16a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
17a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def name(self):
18a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return None
19a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
20a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
21a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def start(self):
22a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return self._counter.timestamps[self._sample_index]
23a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
24a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @start.setter
25a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def start(self, start):
26a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self._counter.timestamps[self._sample_index] = start
27a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def duration(self):
30a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return 0
31a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
32a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
33a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def end(self):
34a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return self.start
35a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  @property
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def thread_start(self):
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return None
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  @property
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def thread_duration(self):
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return None
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  @property
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def thread_end(self):
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return None
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
48a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
49a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass Counter(event_container.TimelineEventContainer):
50a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  """ Stores all the samples for a given counter.
51a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  """
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def __init__(self, parent, category, name):
53a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    super(Counter, self).__init__(name, parent)
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.category = category
55a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.full_name  = category + '.' + name
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.samples = []
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.timestamps = []
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.series_names = []
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.totals = []
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.max_total = 0
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
62a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def IterChildContainers(self):
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    yield # pylint: disable=W0101
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  def IterEventsInThisContainer(self, event_type_predicate, event_predicate):
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if not event_type_predicate(CounterSample) or not self.timestamps:
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    # Pass event_predicate a reused CounterSample instance to avoid
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    # creating a ton of garbage for rejected samples.
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    test_sample = CounterSample(self, 0)
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    for i in xrange(len(self.timestamps)):
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      test_sample._sample_index = i
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if event_predicate(test_sample):
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        yield CounterSample(self, i)
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  @property
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def num_series(self):
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return len(self.series_names)
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  @property
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def num_samples(self):
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return len(self.timestamps)
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
86a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def FinalizeImport(self):
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if self.num_series * self.num_samples != len(self.samples):
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      raise ValueError(
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          'Length of samples must be a multiple of length of timestamps.')
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.totals = []
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.max_total = 0
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if not len(self.samples):
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    max_total = None
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for i in xrange(self.num_samples):
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      total = 0
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      for j in xrange(self.num_series):
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        total += self.samples[i * self.num_series + j]
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        self.totals.append(total)
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if max_total is None or total > max_total:
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        max_total = total
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.max_total = max_total
105