Home | History | Annotate | Download | only in parallel_dd
      1 import os, re, time, subprocess, sys, logging
      2 from autotest_lib.client.bin import test, utils
      3 from autotest_lib.client.common_lib import error
      4 
      5 
      6 class parallel_dd(test.test):
      7     version = 2
      8 
      9     def initialize(self, fs, fstype = 'ext2', megabytes = 1000, streams = 2,
     10                    seq_read = True):
     11         self.megabytes = megabytes
     12         self.blocks = megabytes * 256
     13         self.blocks_per_file = self.blocks / streams
     14         self.fs = fs
     15         self.fstype = fstype
     16         self.streams = streams
     17         self.seq_read = seq_read
     18 
     19         self.old_fstype = self._device_to_fstype('/etc/mtab')
     20         if not self.old_fstype:
     21             self.old_fstpye = self._device_to_fstype('/etc/fstab')
     22         if not self.old_fstype:
     23             self.old_fstype = self.fstype
     24 
     25         logging.info('Dumping %d megabytes across %d streams', megabytes,
     26                      streams)
     27 
     28 
     29     def raw_write(self):
     30         logging.info("Timing raw write of %d megabytes" % self.megabytes)
     31         sys.stdout.flush()
     32         dd = 'dd if=/dev/zero of=%s bs=4k count=%d' % (self.fs.device,
     33                                                        self.blocks)
     34         utils.system(dd + ' > /dev/null')
     35 
     36 
     37     def raw_read(self):
     38         logging.info("Timing raw read of %d megabytes", self.megabytes)
     39         sys.stdout.flush()
     40         dd = 'dd if=%s of=/dev/null bs=4k count=%d' % (self.fs.device,
     41                                                        self.blocks)
     42         utils.system(dd + ' > /dev/null')
     43 
     44 
     45     def fs_write(self):
     46         p = []
     47         # Write out 'streams' files in parallel background tasks
     48         for i in range(self.streams):
     49             file = os.path.join(self.job.tmpdir, 'poo%d' % (i+1))
     50             dd = 'dd if=/dev/zero of=%s bs=4k count=%d' % \
     51                                     (file, self.blocks_per_file)
     52             p.append(subprocess.Popen(dd + ' > /dev/null', shell=True))
     53         logging.info("Waiting for %d streams", self.streams)
     54         # Wait for everyone to complete
     55         for i in range(self.streams):
     56             logging.info("Waiting for %d", p[i].pid)
     57             sys.stdout.flush()
     58             os.waitpid(p[i].pid, 0)
     59         sys.stdout.flush()
     60         sys.stderr.flush()
     61 
     62 
     63     def fs_read(self):
     64         p = []
     65         # Read in 'streams' files in parallel background tasks
     66         for i in range(self.streams):
     67             file = os.path.join(self.job.tmpdir, 'poo%d' % (i+1))
     68             dd = 'dd if=%s of=/dev/null bs=4k count=%d' % \
     69                                     (file, self.blocks_per_file)
     70             if self.seq_read:
     71                 utils.system(dd + ' > /dev/null')
     72             else:
     73                 p.append(subprocess.Popen(dd + ' > /dev/null', shell=True))
     74         if self.seq_read:
     75             return
     76         logging.info("Waiting for %d streams", self.streams)
     77         # Wait for everyone to complete
     78         for i in range(self.streams):
     79             logging.info("Waiting for %d", p[i].pid)
     80             sys.stdout.flush()
     81             os.waitpid(p[i].pid, 0)
     82 
     83 
     84     def _device_to_fstype(self, file):
     85         device = self.fs.device
     86         try:
     87             line = utils.system_output('egrep ^%s %s' % (device, file))
     88             logging.debug(line)
     89             fstype = line.split()[2]
     90             logging.debug('Found %s is type %s from %s', device, fstype, file)
     91             return fstype
     92         except error.CmdError, e:
     93             logging.error('No %s found in %s', device, file)
     94             return None
     95 
     96 
     97     def run_once(self):
     98         try:
     99             self.fs.unmount()
    100         except error.CmdError, e:
    101             pass
    102 
    103         logging.info('------------- Timing raw operations ------------------')
    104         start = time.time()
    105         self.raw_write()
    106         self.raw_write_rate = self.megabytes / (time.time() - start)
    107 
    108         start = time.time()
    109         self.raw_read()
    110         self.raw_read_rate = self.megabytes / (time.time() - start)
    111 
    112         # Set up the filesystem
    113         self.fs.mkfs(self.fstype)
    114         self.fs.mount(None)
    115 
    116         logging.info('------------- Timing fs operations ------------------')
    117         start = time.time()
    118         self.fs_write()
    119         self.fs_write_rate = self.megabytes / (time.time() - start)
    120         self.fs.unmount()
    121 
    122         self.fs.mount(None)
    123         start = time.time()
    124         self.fs_read()
    125         self.fs_read_rate = self.megabytes / (time.time() - start)
    126 
    127         self.write_perf_keyval({
    128             'raw_write' : self.raw_write_rate,
    129             'raw_read'  : self.raw_read_rate,
    130             'fs_write'  : self.fs_write_rate,
    131             'fs_read'   : self.fs_read_rate })
    132 
    133 
    134     def cleanup(self):
    135         try:
    136             self.fs.unmount()
    137         except error.CmdError, e:
    138             pass
    139         logging.debug('\nFormatting %s back to type %s\n', self.fs,
    140                       self.old_fstype)
    141         self.fs.mkfs(self.old_fstype)
    142         self.fs.mount(None)
    143