| # Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.common_lib import error, utils |
| from autotest_lib.client.cros import service_stopper |
| |
| class hardware_MemoryLatency(test.test): |
| """Autotest for measuring memory latency. |
| |
| This uses lat_mem_rd with different parameters to measure memory and cache |
| latencies. |
| """ |
| version = 1 |
| |
| def _run_benchmarks(self, warmup, num_iterations, max_size_mb, |
| sample_size_kb, random, stride): |
| """Run the benchmark. |
| |
| This runs the lat_mem_rd benchmark from lmbench 3. |
| Args: |
| warmup: integer amount of time to spend warming up in microseconds. |
| num_iterations: integer number of times to run the benchmark on each |
| size. |
| max_size_mb: integer size in MB and if sample_size_kb isn't |
| specified, then we'll use this as the only number to report |
| sample_size_kb: a list of integers of specific points where we want |
| to sample the latency |
| random: a boolean which specifies whether a regular stride is used or |
| a fully randomized pointer chase |
| stride: power of two size integer for a stride between pointers |
| """ |
| r = {} |
| sample_sizes = [ int(max_size_mb) * 1024 ] |
| sample_sizes.extend(sample_size_kb) |
| |
| random_flag = '-t' if random else '' |
| |
| cmd = 'lat_mem_rd %s -W %d -N %d %s %d 2>&1' % (random_flag, warmup, |
| num_iterations, max_size_mb, |
| stride) |
| logging.debug('cmd: %s', cmd) |
| out = utils.system_output(cmd) |
| logging.debug('Output: %s', out) |
| |
| # split the output into lines and multiply the first column by |
| # 1024 to get kb, lmbench divides by 1024 but truncates the result |
| # so we have to use rounding to get the correct size |
| for line in out.splitlines(): |
| s = line.split() |
| if len(s) == 2: |
| size = int(round(float(s[0]) * 1024)) |
| latency = float(s[1]) |
| if size in sample_sizes: |
| logging.debug('Matched on size %d', size) |
| if latency <= 0: |
| raise error.TestFail('invalid latency %f' % latency) |
| self._results['ns_' + str(size) + 'KB'] = latency |
| else: |
| logging.debug('Ignoring output line: %s', line) |
| |
| |
| def initialize(self): |
| """Perform necessary initialization prior to test run. |
| |
| Private Attributes: |
| _results: dict containing keyvals with latency measurements |
| _services: service_stopper.ServiceStopper object |
| """ |
| super(hardware_MemoryLatency, self).initialize() |
| self._results = {} |
| stop = [ 'ui' ] |
| stop.extend(service_stopper.ServiceStopper.POWER_DRAW_SERVICES) |
| self._services = service_stopper.ServiceStopper(stop) |
| self._services.stop_services() |
| |
| |
| def run_once(self, warmup=100, num_iterations=20, max_size_mb='32', |
| sample_size_kb=[ int(2), int(192) ], random=False, stride=512): |
| self._run_benchmarks(warmup, num_iterations, max_size_mb, |
| sample_size_kb, random, stride) |
| self.write_perf_keyval(self._results) |
| |
| |
| def cleanup(self): |
| self._services.restore_services() |
| super(hardware_MemoryLatency, self).cleanup() |
| |