summaryrefslogtreecommitdiffstats
path: root/testing/awsy/awsy/test_base_memory_usage.py
blob: 07d65f218f2cdf6df03bf787ebd62a19f84110cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# 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