blob: 4a71d95e11800457449b5056bedb5bde962a0b33 [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import six
import telemetry.timeline.counter as tracing_counter
import telemetry.timeline.event as event_module
import telemetry.timeline.event_container as event_container
import telemetry.timeline.thread as tracing_thread
from telemetry.timeline import memory_dump_event
class Process(event_container.TimelineEventContainer):
"""The Process represents a single userland process in the trace.
"""
def __init__(self, parent, pid):
super(Process, self).__init__('process %s' % pid, parent)
self.pid = pid
self.labels = None
self.uptime_seconds = None
self._threads = {}
self._counters = {}
self._trace_buffer_overflow_event = None
self._memory_dump_events = {}
@property
def trace_buffer_did_overflow(self):
return self._trace_buffer_overflow_event is not None
@property
def trace_buffer_overflow_event(self):
return self._trace_buffer_overflow_event
@property
def threads(self):
return self._threads
@property
def counters(self):
return self._counters
def IterChildContainers(self):
for thread in six.itervalues(self._threads):
yield thread
for counter in six.itervalues(self._counters):
yield counter
def IterEventsInThisContainer(self, event_type_predicate, event_predicate):
if (self.trace_buffer_did_overflow and
event_type_predicate(event_module.TimelineEvent) and
event_predicate(self._trace_buffer_overflow_event)):
yield self._trace_buffer_overflow_event
if (self._memory_dump_events and
event_type_predicate(memory_dump_event.ProcessMemoryDumpEvent)):
for memory_dump in six.itervalues(self._memory_dump_events):
if event_predicate(memory_dump):
yield memory_dump
def GetOrCreateThread(self, tid):
thread = self.threads.get(tid, None)
if thread:
return thread
thread = tracing_thread.Thread(self, tid)
self._threads[tid] = thread
return thread
def GetCounter(self, category, name):
counter_id = category + '.' + name
if counter_id in self.counters:
return self.counters[counter_id]
raise ValueError(
'Counter %s not found in process with id %s.' % (counter_id,
self.pid))
def GetOrCreateCounter(self, category, name):
try:
return self.GetCounter(category, name)
except ValueError:
ctr = tracing_counter.Counter(self, category, name)
self._counters[ctr.full_name] = ctr
return ctr
def AutoCloseOpenSlices(self, max_timestamp, thread_time_bounds):
for thread in six.itervalues(self._threads):
thread.AutoCloseOpenSlices(max_timestamp, thread_time_bounds[thread].max)
def SetTraceBufferOverflowTimestamp(self, timestamp):
# TODO: use instant event for trace_buffer_overflow_event
self._trace_buffer_overflow_event = event_module.TimelineEvent(
"TraceBufferInfo", "trace_buffer_overflowed", timestamp, 0)
def AddMemoryDumpEvent(self, memory_dump):
"""Add a ProcessMemoryDumpEvent to this process."""
if memory_dump.dump_id in self._memory_dump_events:
raise ValueError('Duplicate memory dump id %s in process with id %s.' % (
memory_dump.dump_id, self.pid))
self._memory_dump_events[memory_dump.dump_id] = memory_dump
def FinalizeImport(self):
for thread in six.itervalues(self._threads):
thread.FinalizeImport()
for counter in six.itervalues(self._counters):
counter.FinalizeImport()