1# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6 7from autotest_lib.client.bin import test 8from autotest_lib.client.common_lib import error, utils 9from autotest_lib.client.cros import service_stopper 10 11class hardware_MemoryLatency(test.test): 12 """Autotest for measuring memory latency. 13 14 This uses lat_mem_rd with different parameters to measure memory and cache 15 latencies. 16 """ 17 version = 1 18 19 def _run_benchmarks(self, warmup, num_iterations, max_size_mb, 20 sample_size_kb, random, stride): 21 """Run the benchmark. 22 23 This runs the lat_mem_rd benchmark from lmbench 3. 24 Args: 25 warmup: integer amount of time to spend warming up in microseconds. 26 num_iterations: integer number of times to run the benchmark on each 27 size. 28 max_size_mb: integer size in MB and if sample_size_kb isn't 29 specified, then we'll use this as the only number to report 30 sample_size_kb: a list of integers of specific points where we want 31 to sample the latency 32 random: a boolean which specifies whether a regular stride is used or 33 a fully randomized pointer chase 34 stride: power of two size integer for a stride between pointers 35 """ 36 r = {} 37 sample_sizes = [ int(max_size_mb) * 1024 ] 38 sample_sizes.extend(sample_size_kb) 39 40 random_flag = '-t' if random else '' 41 42 cmd = 'lat_mem_rd %s -W %d -N %d %s %d 2>&1' % (random_flag, warmup, 43 num_iterations, max_size_mb, 44 stride) 45 logging.debug('cmd: %s', cmd) 46 out = utils.system_output(cmd) 47 logging.debug('Output: %s', out) 48 49 # split the output into lines and multiply the first column by 50 # 1024 to get kb, lmbench divides by 1024 but truncates the result 51 # so we have to use rounding to get the correct size 52 for line in out.splitlines(): 53 s = line.split() 54 if len(s) == 2: 55 size = int(round(float(s[0]) * 1024)) 56 latency = float(s[1]) 57 if size in sample_sizes: 58 logging.debug('Matched on size %d', size) 59 if latency <= 0: 60 raise error.TestFail('invalid latency %f' % latency) 61 self._results['ns_' + str(size) + 'KB'] = latency 62 else: 63 logging.debug('Ignoring output line: %s', line) 64 65 66 def initialize(self): 67 """Perform necessary initialization prior to test run. 68 69 Private Attributes: 70 _results: dict containing keyvals with latency measurements 71 _services: service_stopper.ServiceStopper object 72 """ 73 super(hardware_MemoryLatency, self).initialize() 74 self._results = {} 75 stop = [ 'ui' ] 76 stop.extend(service_stopper.ServiceStopper.POWER_DRAW_SERVICES) 77 self._services = service_stopper.ServiceStopper(stop) 78 self._services.stop_services() 79 80 81 def run_once(self, warmup=100, num_iterations=20, max_size_mb='32', 82 sample_size_kb=[ int(2), int(192) ], random=False, stride=512): 83 self._run_benchmarks(warmup, num_iterations, max_size_mb, 84 sample_size_kb, random, stride) 85 self.write_perf_keyval(self._results) 86 87 88 def cleanup(self): 89 self._services.restore_services() 90 super(hardware_MemoryLatency, self).cleanup() 91 92