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.counter as tracing_counter 6import telemetry.timeline.event as event_module 7import telemetry.timeline.event_container as event_container 8import telemetry.timeline.thread as tracing_thread 9from telemetry.timeline import memory_dump_event 10 11 12class Process(event_container.TimelineEventContainer): 13 """The Process represents a single userland process in the trace. 14 """ 15 def __init__(self, parent, pid): 16 super(Process, self).__init__('process %s' % pid, parent) 17 self.pid = pid 18 self.labels = None 19 self._threads = {} 20 self._counters = {} 21 self._trace_buffer_overflow_event = None 22 self._memory_dump_events = {} 23 24 @property 25 def trace_buffer_did_overflow(self): 26 return self._trace_buffer_overflow_event is not None 27 28 @property 29 def trace_buffer_overflow_event(self): 30 return self._trace_buffer_overflow_event 31 32 @property 33 def threads(self): 34 return self._threads 35 36 @property 37 def counters(self): 38 return self._counters 39 40 def IterChildContainers(self): 41 for thread in self._threads.itervalues(): 42 yield thread 43 for counter in self._counters.itervalues(): 44 yield counter 45 46 def IterEventsInThisContainer(self, event_type_predicate, event_predicate): 47 if (self.trace_buffer_did_overflow and 48 event_type_predicate(event_module.TimelineEvent) and 49 event_predicate(self._trace_buffer_overflow_event)): 50 yield self._trace_buffer_overflow_event 51 if (self._memory_dump_events and 52 event_type_predicate(memory_dump_event.ProcessMemoryDumpEvent)): 53 for memory_dump in self._memory_dump_events.itervalues(): 54 if event_predicate(memory_dump): 55 yield memory_dump 56 57 def GetOrCreateThread(self, tid): 58 thread = self.threads.get(tid, None) 59 if thread: 60 return thread 61 thread = tracing_thread.Thread(self, tid) 62 self._threads[tid] = thread 63 return thread 64 65 def GetCounter(self, category, name): 66 counter_id = category + '.' + name 67 if counter_id in self.counters: 68 return self.counters[counter_id] 69 raise ValueError( 70 'Counter %s not found in process with id %s.' % (counter_id, 71 self.pid)) 72 def GetOrCreateCounter(self, category, name): 73 try: 74 return self.GetCounter(category, name) 75 except ValueError: 76 ctr = tracing_counter.Counter(self, category, name) 77 self._counters[ctr.full_name] = ctr 78 return ctr 79 80 def AutoCloseOpenSlices(self, max_timestamp, thread_time_bounds): 81 for thread in self._threads.itervalues(): 82 thread.AutoCloseOpenSlices(max_timestamp, thread_time_bounds[thread].max) 83 84 def SetTraceBufferOverflowTimestamp(self, timestamp): 85 # TODO: use instant event for trace_buffer_overflow_event 86 self._trace_buffer_overflow_event = event_module.TimelineEvent( 87 "TraceBufferInfo", "trace_buffer_overflowed", timestamp, 0) 88 89 def AddMemoryDumpEvent(self, memory_dump): 90 """Add a ProcessMemoryDumpEvent to this process.""" 91 if memory_dump.dump_id in self._memory_dump_events: 92 raise ValueError('Duplicate memory dump id %s in process with id %s.' % ( 93 memory_dump.dump_id, self.pid)) 94 self._memory_dump_events[memory_dump.dump_id] = memory_dump 95 96 def FinalizeImport(self): 97 for thread in self._threads.itervalues(): 98 thread.FinalizeImport() 99 for counter in self._counters.itervalues(): 100 counter.FinalizeImport() 101