1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
| from SimPy.Simulation import * from random import expovariate import argparse import ReadQueue import numpy as np import matplotlib.pyplot as plt
MOV_TIME = .4 NUM_ALGS = 3 NUM_TESTS = 4 BYTES_PER_SEC = 256 SECTORS = 128 DISK_REQUESTS = 1000 MEAN_READ_LENGTH = 4 MAXTIME = 1000000.0 class Controller(Process): """Disk controller generates DISK_REQUESTS # of requests for read head, distributed uniformly with average interarrival time specified by the user.""" def generate(self, mean): for i in range(DISK_REQUESTS): req = ReadRequest(name="Request%03d" % (i), sim=self.sim) self.sim.activate(req, req.request()) nextReq = random.uniform(0, mean*2) if (i == 100): self.sim.byteMon.reset() self.sim.seekMon.reset() self.sim.accessMon.reset() self.sim.rotMon.reset() self.sim.diskMov.reset() yield hold, self, nextReq class ReadRequest(Process): """ReadRequest class simulates a disk head read request sent to the arm""" def request(self): self.trackNum = int(random.uniform(0, 100)) readLength = expovariate(1.0/MEAN_READ_LENGTH) self.sim.byteMon.observe(readLength*BYTES_PER_SEC) yield request,self,self.sim.head,self.trackNum trackDis = abs(self.sim.head.pos - self.trackNum) self.sim.diskMov.observe(trackDis) seekTime = trackDis * MOV_TIME self.sim.seekMon.observe(seekTime) self.sim.head.pos = self.trackNum rotTime = (float(SECTORS)/float(self.sim.head.diskRpm)) * readLength self.sim.rotMon.observe(rotTime) accessTime = seekTime + rotTime self.sim.accessMon.observe(accessTime) yield hold,self,accessTime yield release,self,self.sim.head
class DiskSim(Simulation): """Main Simulation class. Accepts command line input from the user, specifying which algorithm to run, the average inter arrival time, and the maximum rpm speed of the disk. Optionally, a test mode can be invoked to test all variants and graphically display their results. Usage from command line: python DiskSim.py -a FCFS -i 25 -r 7000 --- python DiskSim.py -test True """ def __init__(self): """Constructor for DiskSim simulation""" parser = argparse.ArgumentParser(description='Hard Disk Simulation') parser.add_argument('-test',default=False,help="""test mode will run through the 12 standard test for the disk simulator.""") parser.add_argument('-a', choices=['FCFS','SSF','SCAN'],default='SCAN', help="""the algorithm used by the read head when selecting the next sector. Choices are FCFS, SSF, or SCAN. Default is FCFS""") parser.add_argument('-i', default=5, type=int, help="""average inter-arrival times of disk requests. Will be uniformly distributed; default is 150""") parser.add_argument('-r', default=7200, type=int, help="""maximum rotations per minute achieveable by the hard disk. Default is 7200""") args = parser.parse_args() if (args.test): runTests() print("\nAlgorithm: %s"%args.a) print("Inter-arrival: %d"%args.i) print("Disk RPM: %d"%args.r) self.initialize() self.accessMon = Monitor('Access time (Seek + Rotation)', sim=self) self.seekMon = Monitor('Seek time', sim=self) self.rotMon = Monitor('Rotational latency monitor', sim=self) self.diskMov = Monitor('Disk arm movement', sim=self) self.byteMon = Monitor('Total bytes read', sim=self) self.head = Resource(name="ReadHead",qType= ReadQueue.ReadQ, sim=self) self.head.algorithm = args.a self.head.diskRpm = args.r self.head.pos = 0 controller = Controller('Controller',sim=self) self.activate(controller, controller.generate(mean=args.i), at=0.0) self.simulate(until=MAXTIME) print("Average seek time: %f" %self.seekMon.mean()) print("Average rotational latency: %F"%self.rotMon.mean()) print("Average access time: %f"%self.accessMon.mean()) print("Total seek time: %f"%self.accessMon.total()) print("Total disk arm movement: %d"%self.diskMov.total()) print("Throughput: %f"%(self.byteMon.total()/self.now())) print("Total execution time: %f"%self.now())
def runTests(): """Testing method invoked from user command line option. Tests all the algorithms with all possible standard specifications and displays results to the command line. Also provides a graphical representation of test results.""" sims = [] rects = [] sys.argv=['DiskSim', '-a', 'FCFS', '-i','150', '-r','10000'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'SSF', '-i','150', '-r', '10000'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a','SCAN', '-i','150', '-r', '10000'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'FCFS', '-i','150', '-r','7200'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'SSF', '-i','150', '-r', '7200'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a','SCAN', '-i','150', '-r', '7200'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'FCFS', '-i','5', '-r','10000'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'SSF', '-i','5', '-r', '10000'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a','SCAN', '-i','5', '-r', '10000'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'FCFS', '-i','5', '-r','7200'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a', 'SSF', '-i','5', '-r', '7200'] sims.append(DiskSim()) sys.argv=['DiskSim', '-a','SCAN', '-i','5', '-r', '7200'] sims.append(DiskSim()) ind = np.arange(4) width = 0.30 fig = plt.figure() ax = fig.add_subplot(111) f_res = [[]*NUM_TESTS for x in xrange(NUM_ALGS)] s_res = [[]*NUM_TESTS for x in xrange(NUM_ALGS)] e_res = [[]*NUM_TESTS for x in xrange(NUM_ALGS)] for i in range(4): f_res[0].append(sims[(NUM_ALGS*i+0)].seekMon.mean()) f_res[1].append(sims[(NUM_ALGS*i+0)].rotMon.mean()) f_res[2].append(sims[(NUM_ALGS*i+0)].byteMon.total()/sims[(NUM_ALGS*i+0)].now()) s_res[0].append(sims[(NUM_ALGS*i+1)].seekMon.mean()) s_res[1].append(sims[(NUM_ALGS*i+1)].rotMon.mean()) s_res[2].append(sims[(NUM_ALGS*i+1)].byteMon.total()/sims[(3*i+1)].now()) e_res[0].append(sims[(NUM_ALGS*i+2)].seekMon.mean()) e_res[1].append(sims[(NUM_ALGS*i+2)].rotMon.mean()) e_res[2].append(sims[(NUM_ALGS*i+2)].byteMon.total()/sims[(NUM_ALGS*i+2)].now()) rects.append(ax.bar((ind+width), f_res[0], width, color='red')) rects.append(ax.bar((ind+width*2), s_res[0], width, color='green')) rects.append(ax.bar((ind+width*3), e_res[0], width, color='blue')) ax.set_ylabel('Milliseconds') ax.set_title('Average Seek Time') ax.set_xticks(ind+width*2) ax.set_xticklabels(('150/10000','150/7200','5/10000','5/7200')) ax.legend((rects[0][0],rects[1][0],rects[2][0]), ('FCFS', 'SSF','Elevator/SCAN')) plt.show() fig = plt.figure() ax = fig.add_subplot(111) rects.append(ax.bar((ind+width), f_res[1], width, color='red')) rects.append(ax.bar((ind+width*2), s_res[1], width, color='green')) rects.append(ax.bar((ind+width*3), e_res[1], width, color='blue')) ax.set_ylabel('Milliseconds') ax.set_title('Average Rotational Latency') ax.set_xticks(ind+width*2) ax.set_xticklabels(('150/10000','150/7200','5/10000','5/7200')) ax.legend((rects[0][0],rects[1][0],rects[2][0]), ('FCFS', 'SSF','Elevator/SCAN')) plt.show() fig = plt.figure() ax = fig.add_subplot(111) rects.append(ax.bar((ind+width), f_res[2], width, color='red')) rects.append(ax.bar((ind+width*2), s_res[2], width, color='green')) rects.append(ax.bar((ind+width*3), e_res[2], width, color='blue')) ax.set_ylabel('Milliseconds') ax.set_title('Average Throughput') ax.set_xticks(ind+width*2) ax.set_xticklabels(('150/10000','150/7200','5/10000','5/7200')) ax.legend((rects[0][0],rects[1][0],rects[2][0]), ('FCFS', 'SSF','Elevator/SCAN')) plt.show() sys.exit()
if __name__ == "__main__": DiskSim()
|