1 import os, re 2 from autotest_lib.client.bin import test, utils 3 import postprocessing 4 5 6 class iozone(test.test): 7 """ 8 This autotest module runs the IOzone filesystem benchmark. The benchmark 9 generates and measures a variety of file operations. Iozone has been ported 10 to many machines and runs under many operating systems. 11 12 Iozone is useful for performing a broad filesystem analysis of a vendor's 13 computer platform. The benchmark tests file I/O performance for the 14 following operations: 15 16 Read, write, re-read, re-write, read backwards, read strided, fread, fwrite, 17 random read, pread ,mmap, aio_read, aio_write 18 19 @author: Ying Tao (yingtao (at] cn.ibm.com) 20 @see: http://www.iozone.org 21 """ 22 version = 3 23 24 def initialize(self): 25 self.job.require_gcc() 26 27 28 def setup(self, tarball='iozone3_347.tar'): 29 """ 30 Builds the given version of IOzone from a tarball. 31 @param tarball: Tarball with IOzone 32 @see: http://www.iozone.org/src/current/iozone3_347.tar 33 """ 34 tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir) 35 utils.extract_tarball_to_dir(tarball, self.srcdir) 36 os.chdir(os.path.join(self.srcdir, 'src/current')) 37 utils.system('patch -p3 < ../../../makefile.patch') 38 utils.system('patch -p3 < ../../../clang_fortify.patch') 39 40 ctarget = os.getenv('CTARGET_default') 41 42 if (ctarget == 'armv7a-cros-linux-gnueabi'): 43 utils.make('linux-arm') 44 elif (ctarget == 'i686-pc-linux-gnu'): 45 utils.make('linux') 46 elif (ctarget == 'x86_64-cros-linux-gnu'): 47 utils.make('linux-AMD64') 48 else: 49 utils.make('linux') 50 51 def run_once(self, dir=None, args=None): 52 """ 53 Runs IOzone with appropriate parameters, record raw results in a per 54 iteration raw output file as well as in the results attribute 55 56 @param dir: IOzone file generation dir. 57 @param args: Arguments to the iozone program. 58 """ 59 if not dir: 60 dir = self.tmpdir 61 os.chdir(dir) 62 if not args: 63 args = '-a' 64 65 cmd = os.path.join(self.srcdir, 'src', 'current', 'iozone') 66 self.results = utils.system_output('%s %s' % (cmd, args)) 67 self.auto_mode = ("-a" in args) 68 69 self.results_path = os.path.join(self.resultsdir, 70 'raw_output_%s' % self.iteration) 71 self.analysisdir = os.path.join(self.resultsdir, 72 'analysis_%s' % self.iteration) 73 74 utils.open_write_close(self.results_path, self.results) 75 76 77 def __get_section_name(self, desc): 78 return desc.strip().replace(' ', '_') 79 80 81 def generate_keyval(self): 82 """ 83 Generates a keylist. 84 """ 85 keylist = {} 86 87 if self.auto_mode: 88 labels = ('write', 'rewrite', 'read', 'reread', 'randread', 89 'randwrite', 'bkwdread', 'recordrewrite', 90 'strideread', 'fwrite', 'frewrite', 'fread', 'freread') 91 for line in self.results.splitlines(): 92 fields = line.split() 93 if len(fields) != 15: 94 continue 95 try: 96 fields = tuple([int(i) for i in fields]) 97 except ValueError: 98 continue 99 for l, v in zip(labels, fields[2:]): 100 key_name = "%d-%d-%s" % (fields[0], fields[1], l) 101 keylist[key_name] = v 102 else: 103 child_regexp = re.compile('Children see throughput for[\s]+' 104 '([\d]+)\s+([-\w]+[-\w\s]*)\=[\s]+([\d\.]*) KB/sec') 105 parent_regexp = re.compile('Parent sees throughput for[\s]+' 106 '([\d]+)\s+([-\w]+[-\w\s]*)\=[\s]+([\d\.]*) KB/sec') 107 108 KBsec_regexp = re.compile('\=[\s]+([\d\.]*) KB/sec') 109 KBval_regexp = re.compile('\=[\s]+([\d\.]*) KB') 110 111 section = None 112 w_count = 0 113 114 for line in self.results.splitlines(): 115 line = line.strip() 116 117 # Check for the beginning of a new result section 118 match = child_regexp.search(line) 119 if match: 120 # Extract the section name and the worker count 121 w_count = int(match.group(1)) 122 section = self.__get_section_name(match.group(2)) 123 124 # Output the appropriate keyval pair 125 key_name = '%s-%d-kids' % (section, w_count) 126 keylist[key_name] = match.group(3) 127 continue 128 129 # Check for any other interesting lines 130 if '=' in line: 131 # Is it something we recognize? First check for parent. 132 match = parent_regexp.search(line) 133 if match: 134 # The section name and the worker count better match 135 p_count = int(match.group(1)) 136 p_secnt = self.__get_section_name(match.group(2)) 137 if p_secnt != section or p_count != w_count: 138 continue 139 140 # Set the base name for the keyval 141 basekey = 'parent' 142 else: 143 # Check for the various 'throughput' values 144 if line[3:26] == ' throughput per thread ': 145 basekey = line[0:3] 146 match_x = KBsec_regexp 147 else: 148 # The only other thing we expect is 'Min xfer' 149 if not line.startswith('Min xfer '): 150 continue 151 basekey = 'MinXfer' 152 match_x = KBval_regexp 153 154 match = match_x.search(line) 155 if match: 156 result = match.group(1) 157 key_name = "%s-%d-%s" % (section, w_count, basekey) 158 keylist[key_name] = result 159 160 self.write_perf_keyval(keylist) 161 162 163 def postprocess_iteration(self): 164 self.generate_keyval() 165 if self.auto_mode: 166 a = postprocessing.IOzoneAnalyzer(list_files=[self.results_path], 167 output_dir=self.analysisdir) 168 a.analyze() 169 p = postprocessing.IOzonePlotter(results_file=self.results_path, 170 output_dir=self.analysisdir) 171 p.plot_all() 172