Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(565)

Side by Side Diff: chrome/test/functional/perf_endure.py

Issue 9655016: Enable Deep Memory Profiler in perf_endure.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Performance tests for Chrome Endure (long-running perf tests on Chrome). 6 """Performance tests for Chrome Endure (long-running perf tests on Chrome).
7 7
8 This module accepts the following environment variable inputs: 8 This module accepts the following environment variable inputs:
9 TEST_LENGTH: The number of seconds in which to run each test. 9 TEST_LENGTH: The number of seconds in which to run each test.
10 PERF_STATS_INTERVAL: The number of seconds to wait in-between each sampling 10 PERF_STATS_INTERVAL: The number of seconds to wait in-between each sampling
11 of performance/memory statistics. 11 of performance/memory statistics.
12 """ 12 """
13 13
14 import logging 14 import logging
15 import os 15 import os
16 import re 16 import re
17 import shutil
18 import tempfile
17 import time 19 import time
18 20
19 import perf 21 import perf
20 import pyauto_functional # Must be imported before pyauto. 22 import pyauto_functional # Must be imported before pyauto.
21 import pyauto 23 import pyauto
22 import remote_inspector_client 24 import remote_inspector_client
23 import selenium.common.exceptions 25 import selenium.common.exceptions
24 from selenium.webdriver.support.ui import WebDriverWait 26 from selenium.webdriver.support.ui import WebDriverWait
25 27
28 DMPROF_DIR_PATH = os.path.join(os.path.dirname(__file__),
Nirnimesh 2012/04/09 18:46:44 Unless you want these vars to be accessible from o
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 Done.
29 os.pardir,
30 os.pardir,
31 os.pardir,
32 'tools',
33 'deep_memory_profiler')
34
35 DMPROF_PATH = os.path.join(DMPROF_DIR_PATH,
36 'dmprof.py')
37
38 # TODO(dmikurube): Need to find an actual running chrome.
39 CHROME_BIN_PATH = os.path.join(os.path.dirname(__file__),
40 os.pardir,
41 os.pardir,
42 os.pardir,
43 'out',
44 'Debug',
45 'chrome')
Nirnimesh 2012/04/09 18:46:44 What about non-linux?
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 Done.
26 46
27 class ChromeEndureBaseTest(perf.BasePerfTest): 47 class ChromeEndureBaseTest(perf.BasePerfTest):
28 """Implements common functionality for all Chrome Endure tests. 48 """Implements common functionality for all Chrome Endure tests.
29 49
30 All Chrome Endure test classes should inherit from this class. 50 All Chrome Endure test classes should inherit from this class.
31 """ 51 """
32 52
33 _DEFAULT_TEST_LENGTH_SEC = 60 * 60 * 6 # Tests run for 6 hours. 53 _DEFAULT_TEST_LENGTH_SEC = 60 * 60 * 6 # Tests run for 6 hours.
34 _GET_PERF_STATS_INTERVAL = 60 * 10 # Measure perf stats every 10 minutes. 54 _GET_PERF_STATS_INTERVAL = 60 * 10 # Measure perf stats every 10 minutes.
35 _ERROR_COUNT_THRESHOLD = 300 # Number of ChromeDriver errors to tolerate. 55 _ERROR_COUNT_THRESHOLD = 300 # Number of ChromeDriver errors to tolerate.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 last_perf_stats_time = time.time() 135 last_perf_stats_time = time.time()
116 self._GetPerformanceStats( 136 self._GetPerformanceStats(
117 webapp_name, test_description, tab_title_substring) 137 webapp_name, test_description, tab_title_substring)
118 138
119 if self._iteration_num % 10 == 0: 139 if self._iteration_num % 10 == 0:
120 remaining_time = self._test_length_sec - (time.time() - 140 remaining_time = self._test_length_sec - (time.time() -
121 self._test_start_time) 141 self._test_start_time)
122 logging.info('Chrome interaction #%d. Time remaining in test: %d sec.' % 142 logging.info('Chrome interaction #%d. Time remaining in test: %d sec.' %
123 (self._iteration_num, remaining_time)) 143 (self._iteration_num, remaining_time))
124 144
145 if self._iteration_num % 20 == 5:
Dai Mikurube (NOT FULLTIME) 2012/04/09 09:10:40 Temporary trigger.
Nirnimesh 2012/04/09 18:46:44 Add comments / TODO notes.
dennis_jeffrey 2012/04/09 19:12:38 We'll likely want to be able to turn profiling on/
Dai Mikurube (NOT FULLTIME) 2012/04/11 08:44:02 Ah, exactly. Such an option is required. How can
dennis_jeffrey 2012/04/12 00:51:52 Right now it's done through environment variables.
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 Using an environment variable DEEP_MEMORY_PROFILE_
146 self.HeapProfilerDump('In ChromeEndureControlTest')
147
125 do_scenario() 148 do_scenario()
126 149
127 self._GetPerformanceStats( 150 self._GetPerformanceStats(
128 webapp_name, test_description, tab_title_substring) 151 webapp_name, test_description, tab_title_substring)
129 152
130 def _GetProcessInfo(self, tab_title_substring): 153 def _GetProcessInfo(self, tab_title_substring):
131 """Gets process info associated with an open browser/tab. 154 """Gets process info associated with an open browser/tab.
132 155
133 Args: 156 Args:
134 tab_title_substring: A unique substring contained within the title of 157 tab_title_substring: A unique substring contained within the title of
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 msg='Expected to find 1 %s tab process, but found %d ' 194 msg='Expected to find 1 %s tab process, but found %d '
172 'instead.\nCurrent process info:\n%s.' % ( 195 'instead.\nCurrent process info:\n%s.' % (
173 tab_title_substring, len(tab_proc_info), 196 tab_title_substring, len(tab_proc_info),
174 self.pformat(info))) 197 self.pformat(info)))
175 198
176 browser_proc_info = browser_proc_info[0] 199 browser_proc_info = browser_proc_info[0]
177 tab_proc_info = tab_proc_info[0] 200 tab_proc_info = tab_proc_info[0]
178 return { 201 return {
179 'browser_private_mem': browser_proc_info['working_set_mem']['priv'], 202 'browser_private_mem': browser_proc_info['working_set_mem']['priv'],
180 'tab_private_mem': tab_proc_info['working_set_mem']['priv'], 203 'tab_private_mem': tab_proc_info['working_set_mem']['priv'],
204 'browser_pid': browser_proc_info['pid'],
dennis_jeffrey 2012/04/09 19:12:38 is this value used anywhere?
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 No for now. Removed it.
205 'tab_pid': tab_proc_info['pid'],
181 } 206 }
182 207
183 def _GetPerformanceStats(self, webapp_name, test_description, 208 def _GetPerformanceStats(self, webapp_name, test_description,
184 tab_title_substring): 209 tab_title_substring):
185 """Gets performance statistics and outputs the results. 210 """Gets performance statistics and outputs the results.
186 211
187 Args: 212 Args:
188 webapp_name: A string name for the webapp being tested. Should not 213 webapp_name: A string name for the webapp being tested. Should not
189 include spaces. For example, 'Gmail', 'Docs', or 'Plus'. 214 include spaces. For example, 'Gmail', 'Docs', or 'Plus'.
190 test_description: A string description of what the test does, used for 215 test_description: A string description of what the test does, used for
(...skipping 25 matching lines...) Expand all
216 logging.info(' Tab process private memory: %d KB' % 241 logging.info(' Tab process private memory: %d KB' %
217 proc_info['tab_private_mem']) 242 proc_info['tab_private_mem'])
218 self._tab_process_private_mem_results.append( 243 self._tab_process_private_mem_results.append(
219 (elapsed_time, proc_info['tab_private_mem'])) 244 (elapsed_time, proc_info['tab_private_mem']))
220 245
221 v8_info = self.GetV8HeapStats() # First window, first tab. 246 v8_info = self.GetV8HeapStats() # First window, first tab.
222 v8_mem_used = v8_info['v8_memory_used'] / 1024.0 # Convert to KB. 247 v8_mem_used = v8_info['v8_memory_used'] / 1024.0 # Convert to KB.
223 logging.info(' V8 memory used: %f KB' % v8_mem_used) 248 logging.info(' V8 memory used: %f KB' % v8_mem_used)
224 self._v8_mem_used_results.append((elapsed_time, v8_mem_used)) 249 self._v8_mem_used_results.append((elapsed_time, v8_mem_used))
225 250
251 # TODO(dmikurube): Add --single in dmprof.py?
dennis_jeffrey 2012/04/09 19:12:38 So in general, a test will periodically call HeapP
Dai Mikurube (NOT FULLTIME) 2012/04/11 08:44:02 I'm in tries-and-errors about that. Dumping may t
252 first_dump = ''
253 print '^%s/endure.%05d.\d+.heap$' % (
Nirnimesh 2012/04/09 18:46:44 Use the right logging call instead of print.
Dai Mikurube (NOT FULLTIME) 2012/04/16 09:43:20 Done.
254 self._deep_tempdir, proc_info['tab_pid'])
255 for filename in sorted(os.listdir(self._deep_tempdir)):
256 if re.match('^%s/endure.%05d.\d+.heap$' % (
Nirnimesh 2012/04/09 18:46:44 use os.path.join() instead of hardcoding /
Dai Mikurube (NOT FULLTIME) 2012/04/16 09:43:20 Done.
257 self._deep_tempdir, proc_info['tab_pid']), filename):
258 first_dump = filename
259 break
260
261 # Test printing.
262 if first_dump:
dennis_jeffrey 2012/04/09 19:12:38 What does it mean for a file to be the "first dump
Dai Mikurube (NOT FULLTIME) 2012/04/11 08:44:02 This is just a test printing, and will be removed
263 print 'First Dump: %s' % first_dump
Nirnimesh 2012/04/09 18:46:44 logging.info()?
Dai Mikurube (NOT FULLTIME) 2012/04/16 09:43:20 Done.
264 else:
265 print 'No Dump!'
266 """
267 with open('%s/endure.%05d.json' % (self._deep_tempdir,
Nirnimesh 2012/04/09 18:46:44 use os.path.join
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 Done.
268 proc_info['tab_pid']), 'w+') as json_f:
269 p = subprocess.Popen(
Nirnimesh 2012/04/09 18:46:44 use better varname instead of |p|
Dai Mikurube (NOT FULLTIME) 2012/04/11 08:44:02 Good catch. Thanks.
270 '%s --json %s %s %s' % (DMPROF_PATH,
271 CHROME_BIN_PATH,
272 os.path.join(DMPROF_DIR_PATH, 'dmpolicy'),
273 @@@SNAPSHOT@@@),
274 shell=True, stdout=json_f)
275 p.wait()
Nirnimesh 2012/04/09 18:46:44 you won't need this if you use subprocess.call() i
Dai Mikurube (NOT FULLTIME) 2012/04/16 09:43:20 Finally, this script is required to run on backgro
276 """
277
278 # 2) Parse .json (including only the latest snapshot) file here.
279
226 # Output the results seen so far, to be graphed. 280 # Output the results seen so far, to be graphed.
227 self._OutputPerfGraphValue( 281 self._OutputPerfGraphValue(
228 'TotalDOMNodeCount', self._dom_node_count_results, 'nodes', 282 'TotalDOMNodeCount', self._dom_node_count_results, 'nodes',
229 graph_name='%s%s-Nodes-DOM' % (webapp_name, test_description), 283 graph_name='%s%s-Nodes-DOM' % (webapp_name, test_description),
230 units_x='seconds') 284 units_x='seconds')
231 self._OutputPerfGraphValue( 285 self._OutputPerfGraphValue(
232 'EventListenerCount', self._event_listener_count_results, 'listeners', 286 'EventListenerCount', self._event_listener_count_results, 'listeners',
233 graph_name='%s%s-EventListeners' % (webapp_name, test_description), 287 graph_name='%s%s-EventListeners' % (webapp_name, test_description),
234 units_x='seconds') 288 units_x='seconds')
235 self._OutputPerfGraphValue( 289 self._OutputPerfGraphValue(
236 'BrowserPrivateMemory', self._browser_process_private_mem_results, 'KB', 290 'BrowserPrivateMemory', self._browser_process_private_mem_results, 'KB',
237 graph_name='%s%s-BrowserMem-Private' % (webapp_name, test_description), 291 graph_name='%s%s-BrowserMem-Private' % (webapp_name, test_description),
238 units_x='seconds') 292 units_x='seconds')
239 self._OutputPerfGraphValue( 293 self._OutputPerfGraphValue(
240 'TabPrivateMemory', self._tab_process_private_mem_results, 'KB', 294 'TabPrivateMemory', self._tab_process_private_mem_results, 'KB',
241 graph_name='%s%s-TabMem-Private' % (webapp_name, test_description), 295 graph_name='%s%s-TabMem-Private' % (webapp_name, test_description),
242 units_x='seconds') 296 units_x='seconds')
243 self._OutputPerfGraphValue( 297 self._OutputPerfGraphValue(
244 'V8MemoryUsed', self._v8_mem_used_results, 'KB', 298 'V8MemoryUsed', self._v8_mem_used_results, 'KB',
245 graph_name='%s%s-V8MemUsed' % (webapp_name, test_description), 299 graph_name='%s%s-V8MemUsed' % (webapp_name, test_description),
246 units_x='seconds') 300 units_x='seconds')
301 # 3) Do self._OutputPerfGraphValue for multiple lines, here.
247 302
248 def _GetElement(self, find_by, value): 303 def _GetElement(self, find_by, value):
249 """Gets a WebDriver element object from the webpage DOM. 304 """Gets a WebDriver element object from the webpage DOM.
250 305
251 Args: 306 Args:
252 find_by: A callable that queries WebDriver for an element from the DOM. 307 find_by: A callable that queries WebDriver for an element from the DOM.
253 value: A string value that can be passed to the |find_by| callable. 308 value: A string value that can be passed to the |find_by| callable.
254 309
255 Returns: 310 Returns:
256 The identified WebDriver element object, if found in the DOM, or 311 The identified WebDriver element object, if found in the DOM, or
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 return False 358 return False
304 return True 359 return True
305 360
306 361
307 class ChromeEndureControlTest(ChromeEndureBaseTest): 362 class ChromeEndureControlTest(ChromeEndureBaseTest):
308 """Control tests for Chrome Endure.""" 363 """Control tests for Chrome Endure."""
309 364
310 _webapp_name = 'Control' 365 _webapp_name = 'Control'
311 _tab_title_substring = 'Chrome Endure Control Test' 366 _tab_title_substring = 'Chrome Endure Control Test'
312 367
368 def setUp(self):
dennis_jeffrey 2012/04/09 19:12:38 This only enables profiling in the two control tes
Dai Mikurube (NOT FULLTIME) 2012/04/11 08:44:02 Finally, yes. Is there an efficient way to enable
dennis_jeffrey 2012/04/12 00:51:52 Yes - if you enable profiling above in class Chrom
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 I see. Thank you. I did it in the uploaded code.
369 # TODO(dmikurube): Have to specify "--no-sandbox" for Chrome.
Dai Mikurube (NOT FULLTIME) 2012/04/09 09:20:27 Note: ExtraChromeFlags would work.
370 self._deep_tempdir = tempfile.mkdtemp()
371 os.environ['HEAPPROFILE'] = '%s/endure' % self._deep_tempdir
Nirnimesh 2012/04/09 18:46:44 os.path.join
Dai Mikurube (NOT FULLTIME) 2012/04/13 11:16:49 Done.
372 os.environ['DEEP_HEAP_PROFILE'] = 'True'
373 ChromeEndureBaseTest.setUp(self)
374
375 def tearDown(self):
376 del os.environ['DEEP_HEAP_PROFILE']
377 del os.environ['HEAPPROFILE']
378 ChromeEndureBaseTest.tearDown(self)
379 # shutil.rmtree(self._deep_tempdir)
380
313 def testControlAttachDetachDOMTree(self): 381 def testControlAttachDetachDOMTree(self):
314 """Continually attach and detach a DOM tree from a basic document.""" 382 """Continually attach and detach a DOM tree from a basic document."""
315 test_description = 'AttachDetachDOMTree' 383 test_description = 'AttachDetachDOMTree'
316 url = self.GetHttpURLForDataPath('chrome_endure', 'endurance_control.html') 384 url = self.GetHttpURLForDataPath('chrome_endure', 'endurance_control.html')
317 self.NavigateToURL(url) 385 self.NavigateToURL(url)
318 loaded_tab_title = self.GetActiveTabTitle() 386 loaded_tab_title = self.GetActiveTabTitle()
319 self.assertTrue(self._tab_title_substring in loaded_tab_title, 387 self.assertTrue(self._tab_title_substring in loaded_tab_title,
320 msg='Loaded tab title does not contain "%s": "%s"' % 388 msg='Loaded tab title does not contain "%s": "%s"' %
321 (self._tab_title_substring, loaded_tab_title)) 389 (self._tab_title_substring, loaded_tab_title))
322 390
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 self._driver, self._wait, 'id("state")[text()="offline"]'): 906 self._driver, self._wait, 'id("state")[text()="offline"]'):
839 self._num_errors += 1 907 self._num_errors += 1
840 time.sleep(1) 908 time.sleep(1)
841 909
842 self._RunEndureTest(self._webapp_name, self._tab_title_substring, 910 self._RunEndureTest(self._webapp_name, self._tab_title_substring,
843 test_description, scenario) 911 test_description, scenario)
844 912
845 913
846 if __name__ == '__main__': 914 if __name__ == '__main__':
847 pyauto_functional.Main() 915 pyauto_functional.Main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698