• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7import re
8
9from autotest_lib.client.bin import test, utils
10from autotest_lib.client.common_lib import error
11
12_RESULT_STRING = 'Average page access speed: (\d+)'
13
14class hardware_MemoryZRAMThroughput(test.test):
15    """
16    This test uses a large buffer to measure the page access throughput with
17    and without ZRAM.
18    """
19    version = 1
20
21    def initialize(self):
22        utils.system('stop ui', ignore_status=True)
23        self._PATTERN = re.compile(_RESULT_STRING)
24
25    def _log_results(self, key, out):
26        logging.info("test output: %s", out)
27        pages_per_second = 0
28        data_points = 0
29        for line in out.splitlines():
30            result = self._PATTERN.match(line)
31            if result:
32                pages_per_second += float(result.group(1))
33                data_points += 1
34                continue
35
36        if data_points == 0:
37            raise error.TestError('Test results not found')
38
39        # Take the average of all data points. Currently when --fork is
40        # passed to memory-eater, there will be two data points from two
41        # processes.
42        average_pages_per_second = pages_per_second / data_points
43        self.output_perf_value(description=key,
44                               value=average_pages_per_second,
45                               higher_is_better=True,
46                               units='pages_per_sec')
47
48        return average_pages_per_second
49
50    def run_once(self):
51        mem_size = utils.memtotal()
52        swap_size = utils.swaptotal()
53        logging.info("MemTotal: %.0f KB", mem_size)
54        logging.info("SwapTotal: %.0f KB", swap_size)
55
56        # First run memory-eater wth 60% of total memory size to measure the
57        # page access throughput
58        cmd = ("memory-eater --size %d --speed --repeat 4 --chunk 500 "
59               "--wait 0" % int(mem_size * 0.60 / 1024))
60        logging.debug('cmd: %s', cmd)
61        out = utils.system_output(cmd)
62        self._log_results("60_Percent_RAM", out)
63
64        # Then run memory-eater wth total memory + 30% swap size to measure the
65        # page access throughput. On 32-bit system with 4GB of RAM, the memory
66        # footprint needed to generate enough memory pressure is larger than
67        # a single user-space process can own. So we divide the memory usage
68        # by half and the test itself will fork a child process to double the
69        # memory usage. Each process will take turns to access 500 pages
70        # (via --chunk) until all pages are accessed 4 times (via --repeat).
71        half_mem_pressure_size = int((mem_size+swap_size * 0.3) / 1024) / 2;
72        cmd = ("memory-eater --size %d --speed --fork --repeat 4 --chunk 500"
73               "--wait 0" % half_mem_pressure_size)
74        logging.debug('cmd: %s', cmd)
75        out = utils.system_output(cmd)
76        self._log_results("30_Percent_SWAP", out)
77
78    def cleanup(self):
79        utils.system('start ui')
80