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