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         utils.system('patch -p3 < ../../../clang_fortify.patch')
     39 
     40         ctarget = os.getenv('CTARGET_default')
     41 
     42         if (ctarget == 'armv7a-cros-linux-gnueabihf'):
     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