# 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/. import os import sys AWSY_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) if AWSY_PATH not in sys.path: sys.path.append(AWSY_PATH) from awsy.awsy_test_case import AwsyTestCase # A description of each checkpoint and the root path to it. CHECKPOINTS = [ { "name": "After tabs open [+30s, forced GC]", "path": "memory-report-TabsOpenForceGC-4.json.gz", "name_filter": ["web ", "Web Content"], # We only want the content process "median": True, # We want the median from all content processes }, ] # A description of each perfherder suite and the path to its values. PERF_SUITES = [ {"name": "Base Content Resident Unique Memory", "node": "resident-unique"}, {"name": "Base Content Heap Unclassified", "node": "explicit/heap-unclassified"}, {"name": "Base Content JS", "node": "js-main-runtime/", "alertThreshold": 0.25}, {"name": "Base Content Explicit", "node": "explicit/"}, ] class TestMemoryUsage(AwsyTestCase): """ Provides a base case test that just loads about:memory and reports the memory usage of a single content process. """ def urls(self): return self._urls def perf_suites(self): return PERF_SUITES def perf_checkpoints(self): return CHECKPOINTS def perf_extra_opts(self): return self._extra_opts def setUp(self): AwsyTestCase.setUp(self) self.logger.info("setting up!") # Override AwsyTestCase value, this is always going to be 1 iteration. self._iterations = 1 # Override "entities" from our configuration. # # We aim to load a number of about:blank pages exactly matching the # number of content processes we can have. After this we should no # longer have a preallocated content process (although to be sure we # explicitly drop it at the end of the test). process_count = self.marionette.get_pref("dom.ipc.processCount") self._pages_to_load = process_count self._urls = ["about:blank"] * process_count if self.marionette.get_pref("fission.autostart"): self._extra_opts = ["fission"] else: self._extra_opts = None self.logger.info( "areweslimyet run by %d pages, " "%d iterations, %d perTabPause, %d settleWaitTime, " "%d content processes" % ( self._pages_to_load, self._iterations, self._perTabPause, self._settleWaitTime, process_count, ) ) self.logger.info("done setting up!") def tearDown(self): self.logger.info("tearing down!") AwsyTestCase.tearDown(self) self.logger.info("done tearing down!") def set_preallocated_process_enabled_state(self, enabled): """Sets the pref that controls whether we have a preallocated content process to the given value. This will cause the preallocated process to be destroyed or created as appropriate. """ if enabled: self.logger.info("re-enabling preallocated process") else: self.logger.info("disabling preallocated process") self.marionette.set_pref("dom.ipc.processPrelaunch.enabled", enabled) def test_open_tabs(self): """Marionette test entry that returns an array of checkpoint arrays. This will generate a set of checkpoints for each iteration requested. Upon successful completion the results will be stored in |self.testvars["results"]| and accessible to the test runner via the |testvars| object it passed in. """ # setup the results array results = [[] for _ in range(self.iterations())] def create_checkpoint(name, iteration, minimize=False): checkpoint = self.do_memory_report(name, iteration, minimize) self.assertIsNotNone(checkpoint, "Checkpoint was recorded") results[iteration].append(checkpoint) # As long as we force the number of iterations to 1 in setUp() above, # we don't need to loop over this work. assert self._iterations == 1 self.open_pages() self.set_preallocated_process_enabled_state(False) self.settle() self.settle() create_checkpoint("TabsOpenForceGC", 0, minimize=True) self.set_preallocated_process_enabled_state(True) # (If we wanted to do something after the preallocated process has been # recreated, we should call self.settle() again to wait for it.) # TODO(ER): Temporary hack until bug 1121139 lands self.logger.info("setting results") self.testvars["results"] = results