1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5from __future__ import absolute_import 6 7import os 8import sys 9 10AWSY_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 11if AWSY_PATH not in sys.path: 12 sys.path.append(AWSY_PATH) 13 14from awsy.awsy_test_case import AwsyTestCase 15 16# A description of each checkpoint and the root path to it. 17CHECKPOINTS = [ 18 { 19 'name': "After tabs open [+30s, forced GC]", 20 'path': "memory-report-TabsOpenForceGC-4.json.gz", 21 'name_filter': 'Web Content', # We only want the content process 22 'median': True, # We want the median from all content processes 23 }, 24] 25 26# A description of each perfherder suite and the path to its values. 27PERF_SUITES = [ 28 {'name': "Base Content Resident Unique Memory", 'node': "resident-unique"}, 29 {'name': "Base Content Heap Unclassified", 'node': "explicit/heap-unclassified"}, 30 {'name': "Base Content JS", 'node': "js-main-runtime/", 'alertThreshold': 0.25}, 31 {'name': "Base Content Explicit", 'node': "explicit/"}, 32] 33 34 35class TestMemoryUsage(AwsyTestCase): 36 """ 37 Provides a base case test that just loads about:memory and reports the 38 memory usage of a single content process. 39 """ 40 41 def urls(self): 42 return self._urls 43 44 def perf_suites(self): 45 return PERF_SUITES 46 47 def perf_checkpoints(self): 48 return CHECKPOINTS 49 50 def setUp(self): 51 AwsyTestCase.setUp(self) 52 self.logger.info("setting up!") 53 54 # Override AwsyTestCase value, this is always going to be 1 iteration. 55 self._iterations = 1 56 57 # Override "entities" from our configuration. 58 # 59 # We aim to load a number of about:blank pages exactly matching the 60 # number of content processes we can have. After this we should no 61 # longer have a preallocated content process (although to be sure we 62 # explicitly drop it at the end of the test). 63 process_count = self.marionette.get_pref('dom.ipc.processCount') 64 self._pages_to_load = process_count 65 self._urls = ['about:blank'] * process_count 66 67 self.logger.info("areweslimyet run by %d pages, " 68 "%d iterations, %d perTabPause, %d settleWaitTime, " 69 "%d content processes" 70 % (self._pages_to_load, self._iterations, 71 self._perTabPause, self._settleWaitTime, 72 process_count)) 73 self.logger.info("done setting up!") 74 75 def tearDown(self): 76 self.logger.info("tearing down!") 77 AwsyTestCase.tearDown(self) 78 self.logger.info("done tearing down!") 79 80 def set_preallocated_process_enabled_state(self, enabled): 81 """Sets the pref that controls whether we have a preallocated content 82 process to the given value. 83 84 This will cause the preallocated process to be destroyed or created 85 as appropriate. 86 """ 87 if enabled: 88 self.logger.info('re-enabling preallocated process') 89 else: 90 self.logger.info('disabling preallocated process') 91 self.marionette.set_pref('dom.ipc.processPrelaunch.enabled', enabled) 92 93 def test_open_tabs(self): 94 """Marionette test entry that returns an array of checkoint arrays. 95 96 This will generate a set of checkpoints for each iteration requested. 97 Upon succesful completion the results will be stored in 98 |self.testvars["results"]| and accessible to the test runner via the 99 |testvars| object it passed in. 100 """ 101 # setup the results array 102 results = [[] for _ in range(self.iterations())] 103 104 def create_checkpoint(name, iteration): 105 checkpoint = self.do_memory_report(name, iteration) 106 self.assertIsNotNone(checkpoint, "Checkpoint was recorded") 107 results[iteration].append(checkpoint) 108 109 # As long as we force the number of iterations to 1 in setUp() above, 110 # we don't need to loop over this work. 111 assert self._iterations == 1 112 self.open_pages() 113 self.set_preallocated_process_enabled_state(False) 114 self.settle() 115 self.settle() 116 self.assertTrue(self.do_full_gc()) 117 self.settle() 118 create_checkpoint("TabsOpenForceGC", 0) 119 self.set_preallocated_process_enabled_state(True) 120 # (If we wanted to do something after the preallocated process has been 121 # recreated, we should call self.settle() again to wait for it.) 122 123 # TODO(ER): Temporary hack until bug 1121139 lands 124 self.logger.info("setting results") 125 self.testvars["results"] = results 126