Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / testing / performance / talos / cmanager_mac.py
blob10e1dbdcd7fd8478725f368586169e18ab136134
1 #!/usr/bin/env python
3 # ***** BEGIN LICENSE BLOCK *****
4 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 # The contents of this file are subject to the Mozilla Public License Version
7 # 1.1 (the "License"); you may not use this file except in compliance with
8 # the License. You may obtain a copy of the License at
9 # http://www.mozilla.org/MPL/
11 # Software distributed under the License is distributed on an "AS IS" basis,
12 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 # for the specific language governing rights and limitations under the
14 # License.
16 # The Original Code is standalone Firefox Windows performance test.
18 # The Initial Developer of the Original Code is Google Inc.
19 # Portions created by the Initial Developer are Copyright (C) 2006
20 # the Initial Developer. All Rights Reserved.
22 # Contributor(s):
23 # Annie Sullivan <annie.sullivan@gmail.com> (original author)
24 # Ben Hearsum <bhearsum@wittydomain.com> (ported to linux)
25 # Zach Lipton <zach@zachlipton.com> (Mac port)
27 # Alternatively, the contents of this file may be used under the terms of
28 # either the GNU General Public License Version 2 or later (the "GPL"), or
29 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 # in which case the provisions of the GPL or the LGPL are applicable instead
31 # of those above. If you wish to allow use of your version of this file only
32 # under the terms of either the GPL or the LGPL, and not to allow others to
33 # use your version of this file under the terms of the MPL, indicate your
34 # decision by deleting the provisions above and replace them with the notice
35 # and other provisions required by the GPL or the LGPL. If you do not delete
36 # the provisions above, a recipient may use your version of this file under
37 # the terms of any one of the MPL, the GPL or the LGPL.
39 # ***** END LICENSE BLOCK *****
41 """A set of functions to run the Tp test.
43 The Tp test measures page load times in Firefox. It does this with a
44 JavaScript script that opens a new window and cycles through page loads
45 from the local disk, timing each one. The script dumps the sum of the
46 mean times to open each page, and the standard deviation, to standard out.
47 We can also measure performance attributes during the test. See below for
48 what can be monitored
49 """
51 __author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
54 import os
55 import time
56 import threading
57 import subprocess
59 import ffprocess
61 def GetProcessData(pid):
62 """Runs a ps on the process identified by pid and returns the output line
63 as a list (pid, vsz, rss)
64 """
65 command = ['ps -o pid,vsize,rss -p'+str(pid)]
66 handle = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True, shell=True)
67 handle.wait()
68 data = handle.stdout.readlines()
70 # First line is header output should look like:
71 # PID VSZ RSS
72 # 3210 75964 920
73 line = data[1]
74 line = line.split()
75 if (line[0] == str(pid)):
76 return line
78 def GetPrivateBytes(pid):
79 """Calculate the amount of private, writeable memory allocated to a process.
80 """
81 psData = GetProcessData(pid)
82 return psData[2]
85 def GetResidentSize(pid):
86 """Retrieve the current resident memory for a given process"""
87 psData = GetProcessData(pid)
88 return psData[1]
90 def GetCpuTime(pid):
91 # return all zeros for now on this platform as per 7/18/07 perf meeting
92 return 0
94 counterDict = {}
95 counterDict["Private Bytes"] = GetPrivateBytes
96 counterDict["RSS"] = GetResidentSize
97 counterDict["% Processor Time"] = GetCpuTime
99 class CounterManager(threading.Thread):
100 """This class manages the monitoring of a process with any number of
101 counters.
103 A counter can be any function that takes an argument of one pid and
104 returns a piece of data about that process.
105 Some examples are: CalcCPUTime, GetResidentSize, and GetPrivateBytes
108 pollInterval = .25
110 def __init__(self, process, counters=None):
111 """Args:
112 counters: A list of counters to monitor. Any counters whose name does
113 not match a key in 'counterDict' will be ignored.
115 self.allCounters = {}
116 self.registeredCounters = {}
117 self.process = process
118 self.runThread = False
119 self.pid = -1
121 self._loadCounters()
122 self.registerCounters(counters)
124 threading.Thread.__init__(self)
126 def _loadCounters(self):
127 """Loads all of the counters defined in the counterDict"""
128 for counter in counterDict.keys():
129 self.allCounters[counter] = counterDict[counter]
131 def registerCounters(self, counters):
132 """Registers a list of counters that will be monitoring.
133 Only counters whose names are found in allCounters will be added
135 for counter in counters:
136 if counter in self.allCounters:
137 self.registeredCounters[counter] = \
138 [self.allCounters[counter], []]
140 def unregisterCounters(self, counters):
141 """Unregister a list of counters.
142 Only counters whose names are found in registeredCounters will be
143 paid attention to
145 for counter in counters:
146 if counter in self.registeredCounters:
147 del self.registeredCounters[counter]
149 def getRegisteredCounters(self):
150 """Returns a list of the registered counters."""
151 return keys(self.registeredCounters)
153 def getCounterValue(self, counterName):
154 """Returns the last value of the counter 'counterName'"""
155 try:
156 if counterName is "% Processor Time":
157 return self._getCounterAverage(counterName)
158 else:
159 return self.registeredCounters[counterName][1][-1]
160 except:
161 return None
163 def _getCounterAverage(self, counterName):
164 """Returns the average value of the counter 'counterName'"""
165 try:
166 total = 0
167 for v in self.registeredCounters[counterName][1]:
168 total += v
169 return total / len(self.registeredCounters[counterName][1])
170 except:
171 return None
173 def getProcess(self):
174 """Returns the process currently associated with this CounterManager"""
175 return self.process
177 def startMonitor(self):
178 """Starts the monitoring process.
179 Throws an exception if any error occurs
181 # TODO: make this function less ugly
182 try:
183 # the last process is the useful one
184 self.pid = ffprocess.GetPidsByName(self.process)[-1]
185 self.runThread = True
186 self.start()
187 except:
188 print 'WARNING: problem starting counter monitor'
190 def stopMonitor(self):
191 """Stops the monitor"""
192 # TODO: should probably wait until we know run() is completely stopped
193 # before setting self.pid to None. Use a lock?
194 self.runThread = False
196 def run(self):
197 """Performs the actual monitoring of the process. Will keep running
198 until stopMonitor() is called
200 while self.runThread:
201 for counter in self.registeredCounters.keys():
202 # counter[0] is a function that gets the current value for
203 # a counter
204 # counter[1] is a list of recorded values
205 try:
206 self.registeredCounters[counter][1].append(
207 self.registeredCounters[counter][0](self.pid))
208 except:
209 # if a counter throws an exception, remove it
210 self.unregisterCounters([counter])
212 time.sleep(self.pollInterval)