• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_container as event_container
6
7
8# Doesn't inherit from TimelineEvent because its only a temporary wrapper of a
9# counter sample into an event. During stable operation, the samples are stored
10# a dense array of values rather than in the long-form done by an Event.
11class CounterSample(object):
12  def __init__(self, counter, sample_index):
13    self._counter = counter
14    self._sample_index = sample_index
15
16  @property
17  def category(self):
18    return self._counter.category
19
20  @property
21  def name(self):
22    return self._counter.full_name
23
24  @property
25  def value(self):
26    return self._counter.samples[self._sample_index]
27
28  @property
29  def start(self):
30    return self._counter.timestamps[self._sample_index]
31
32  @start.setter
33  def start(self, start):
34    self._counter.timestamps[self._sample_index] = start
35
36  @property
37  def duration(self):
38    return 0
39
40  @property
41  def end(self):
42    return self.start
43
44  @property
45  def thread_start(self):
46    return None
47
48  @property
49  def thread_duration(self):
50    return None
51
52  @property
53  def thread_end(self):
54    return None
55
56
57class Counter(event_container.TimelineEventContainer):
58  """ Stores all the samples for a given counter.
59  """
60  def __init__(self, parent, category, name):
61    super(Counter, self).__init__(name, parent)
62    self.category = category
63    self.full_name = category + '.' + name
64    self.samples = []
65    self.timestamps = []
66    self.series_names = []
67    self.totals = []
68    self.max_total = 0
69
70  def IterChildContainers(self):
71    return
72    yield # pylint: disable=unreachable
73
74  def IterEventsInThisContainer(self, event_type_predicate, event_predicate):
75    if not event_type_predicate(CounterSample) or not self.timestamps:
76      return
77
78    # Pass event_predicate a reused CounterSample instance to avoid
79    # creating a ton of garbage for rejected samples.
80    test_sample = CounterSample(self, 0)
81    for i in xrange(len(self.timestamps)):
82      test_sample._sample_index = i  # pylint: disable=protected-access
83      if event_predicate(test_sample):
84        yield CounterSample(self, i)
85
86  @property
87  def num_series(self):
88    return len(self.series_names)
89
90  @property
91  def num_samples(self):
92    return len(self.timestamps)
93
94  def FinalizeImport(self):
95    if self.num_series * self.num_samples != len(self.samples):
96      raise ValueError(
97          'Length of samples must be a multiple of length of timestamps.')
98
99    self.totals = []
100    self.max_total = 0
101    if not len(self.samples):
102      return
103
104    max_total = None
105    for i in xrange(self.num_samples):
106      total = 0
107      for j in xrange(self.num_series):
108        total += self.samples[i * self.num_series + j]
109        self.totals.append(total)
110      if max_total is None or total > max_total:
111        max_total = total
112    self.max_total = max_total
113