# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. """CounterManager for Mac OSX""" import subprocess import sys from talos.cmanager_base import CounterManager def GetProcessData(pid): """Runs a ps on the process identified by pid and returns the output line as a list (pid, vsz, rss) """ command = ["ps -o pid,vsize,rss -p" + str(pid)] try: handle = subprocess.Popen( command, stdout=subprocess.PIPE, universal_newlines=True, shell=True ) handle.wait() data = handle.stdout.readlines() except Exception: print("Unexpected error executing '%s': %s", (command, sys.exc_info())) raise # First line is header output should look like: # PID VSZ RSS # 3210 75964 920 line = data[1] line = line.split() if line[0] == str(pid): return line def GetPrivateBytes(pid): """Calculate the amount of private, writeable memory allocated to a process. """ psData = GetProcessData(pid) return int(psData[1]) * 1024 # convert to bytes def GetResidentSize(pid): """Retrieve the current resident memory for a given process""" psData = GetProcessData(pid) return int(psData[2]) * 1024 # convert to bytes class MacCounterManager(CounterManager): """This class manages the monitoring of a process with any number of counters. A counter can be any function that takes an argument of one pid and returns a piece of data about that process. Some examples are: CalcCPUTime, GetResidentSize, and GetPrivateBytes """ counterDict = {"Private Bytes": GetPrivateBytes, "RSS": GetResidentSize} def __init__(self, process_name, process, counters): """Args: counters: A list of counters to monitor. Any counters whose name does not match a key in 'counterDict' will be ignored. """ CounterManager.__init__(self) # the last process is the useful one self.pid = process.pid self._loadCounters() self.registerCounters(counters) def getCounterValue(self, counterName): """Returns the last value of the counter 'counterName'""" if counterName not in self.registeredCounters: print( "Warning: attempting to collect counter %s and it is not" " registered" % counterName ) return try: return self.registeredCounters[counterName][0](self.pid) except Exception as e: print( "Error in collecting counter: %s, pid: %s, exception: %s" % (counterName, self.pid, e) )