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 39 ctarget = os.getenv('CTARGET_default') 40 41 if (ctarget == 'armv7a-cros-linux-gnueabi'): 42 utils.make('linux-arm') 43 elif (ctarget == 'i686-pc-linux-gnu'): 44 utils.make('linux') 45 elif (ctarget == 'x86_64-cros-linux-gnu'): 46 utils.make('linux-AMD64') 47 else: 48 utils.make('linux') 49 50 def run_once(self, dir=None, args=None): 51 """ 52 Runs IOzone with appropriate parameters, record raw results in a per 53 iteration raw output file as well as in the results attribute 54 55 @param dir: IOzone file generation dir. 56 @param args: Arguments to the iozone program. 57 """ 58 if not dir: 59 dir = self.tmpdir 60 os.chdir(dir) 61 if not args: 62 args = '-a' 63 64 cmd = os.path.join(self.srcdir, 'src', 'current', 'iozone') 65 self.results = utils.system_output('%s %s' % (cmd, args)) 66 self.auto_mode = ("-a" in args) 67 68 self.results_path = os.path.join(self.resultsdir, 69 'raw_output_%s' % self.iteration) 70 self.analysisdir = os.path.join(self.resultsdir, 71 'analysis_%s' % self.iteration) 72 73 utils.open_write_close(self.results_path, self.results) 74 75 76 def __get_section_name(self, desc): 77 return desc.strip().replace(' ', '_') 78 79 80 def generate_keyval(self): 81 keylist = {} 82 83 if self.auto_mode: 84 labels = ('write', 'rewrite', 'read', 'reread', 'randread', 85 'randwrite', 'bkwdread', 'recordrewrite', 86 'strideread', 'fwrite', 'frewrite', 'fread', 'freread') 87 for line in self.results.splitlines(): 88 fields = line.split() 89 if len(fields) != 15: 90 continue 91 try: 92 fields = tuple([int(i) for i in fields]) 93 except ValueError: 94 continue 95 for l, v in zip(labels, fields[2:]): 96 key_name = "%d-%d-%s" % (fields[0], fields[1], l) 97 keylist[key_name] = v 98 else: 99 child_regexp = re.compile('Children see throughput for[\s]+' 100 '([\d]+)\s+([-\w]+[-\w\s]*)\=[\s]+([\d\.]*) KB/sec') 101 parent_regexp = re.compile('Parent sees throughput for[\s]+' 102 '([\d]+)\s+([-\w]+[-\w\s]*)\=[\s]+([\d\.]*) KB/sec') 103 104 KBsec_regexp = re.compile('\=[\s]+([\d\.]*) KB/sec') 105 KBval_regexp = re.compile('\=[\s]+([\d\.]*) KB') 106 107 section = None 108 w_count = 0 109 110 for line in self.results.splitlines(): 111 line = line.strip() 112 113 # Check for the beginning of a new result section 114 match = child_regexp.search(line) 115 if match: 116 # Extract the section name and the worker count 117 w_count = int(match.group(1)) 118 section = self.__get_section_name(match.group(2)) 119 120 # Output the appropriate keyval pair 121 key_name = '%s-%d-kids' % (section, w_count) 122 keylist[key_name] = match.group(3) 123 continue 124 125 # Check for any other interesting lines 126 if '=' in line: 127 # Is it something we recognize? First check for parent. 128 match = parent_regexp.search(line) 129 if match: 130 # The section name and the worker count better match 131 p_count = int(match.group(1)) 132 p_secnt = self.__get_section_name(match.group(2)) 133 if p_secnt != section or p_count != w_count: 134 continue 135 136 # Set the base name for the keyval 137 basekey = 'parent' 138 else: 139 # Check for the various 'throughput' values 140 if line[3:26] == ' throughput per thread ': 141 basekey = line[0:3] 142 match_x = KBsec_regexp 143 else: 144 # The only other thing we expect is 'Min xfer' 145 if not line.startswith('Min xfer '): 146 continue 147 basekey = 'MinXfer' 148 match_x = KBval_regexp 149 150 match = match_x.search(line) 151 if match: 152 result = match.group(1) 153 key_name = "%s-%d-%s" % (section, w_count, basekey) 154 keylist[key_name] = result 155 156 self.write_perf_keyval(keylist) 157 158 159 def postprocess_iteration(self): 160 self.generate_keyval() 161 if self.auto_mode: 162 a = postprocessing.IOzoneAnalyzer(list_files=[self.results_path], 163 output_dir=self.analysisdir) 164 a.analyze() 165 p = postprocessing.IOzonePlotter(results_file=self.results_path, 166 output_dir=self.analysisdir) 167 p.plot_all() 168