Home | History | Annotate | Download | only in iozone
      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