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 name(self): 18 return None 19 20 @property 21 def start(self): 22 return self._counter.timestamps[self._sample_index] 23 24 @start.setter 25 def start(self, start): 26 self._counter.timestamps[self._sample_index] = start 27 28 @property 29 def duration(self): 30 return 0 31 32 @property 33 def end(self): 34 return self.start 35 36 @property 37 def thread_start(self): 38 return None 39 40 @property 41 def thread_duration(self): 42 return None 43 44 @property 45 def thread_end(self): 46 return None 47 48 49class Counter(event_container.TimelineEventContainer): 50 """ Stores all the samples for a given counter. 51 """ 52 def __init__(self, parent, category, name): 53 super(Counter, self).__init__(name, parent) 54 self.category = category 55 self.full_name = category + '.' + name 56 self.samples = [] 57 self.timestamps = [] 58 self.series_names = [] 59 self.totals = [] 60 self.max_total = 0 61 62 def IterChildContainers(self): 63 return 64 yield # pylint: disable=W0101 65 66 def IterEventsInThisContainer(self, event_type_predicate, event_predicate): 67 if not event_type_predicate(CounterSample) or not self.timestamps: 68 return 69 70 # Pass event_predicate a reused CounterSample instance to avoid 71 # creating a ton of garbage for rejected samples. 72 test_sample = CounterSample(self, 0) 73 for i in xrange(len(self.timestamps)): 74 test_sample._sample_index = i 75 if event_predicate(test_sample): 76 yield CounterSample(self, i) 77 78 @property 79 def num_series(self): 80 return len(self.series_names) 81 82 @property 83 def num_samples(self): 84 return len(self.timestamps) 85 86 def FinalizeImport(self): 87 if self.num_series * self.num_samples != len(self.samples): 88 raise ValueError( 89 'Length of samples must be a multiple of length of timestamps.') 90 91 self.totals = [] 92 self.max_total = 0 93 if not len(self.samples): 94 return 95 96 max_total = None 97 for i in xrange(self.num_samples): 98 total = 0 99 for j in xrange(self.num_series): 100 total += self.samples[i * self.num_series + j] 101 self.totals.append(total) 102 if max_total is None or total > max_total: 103 max_total = total 104 self.max_total = max_total 105