[haizea-commit] r543 - trunk/src/haizea/resourcemanager

haizea-commit at mailman.cs.uchicago.edu haizea-commit at mailman.cs.uchicago.edu
Wed Nov 19 18:29:41 CST 2008


Author: borja
Date: 2008-11-19 18:29:39 -0600 (Wed, 19 Nov 2008)
New Revision: 543

Modified:
   trunk/src/haizea/resourcemanager/datastruct.py
   trunk/src/haizea/resourcemanager/rm.py
   trunk/src/haizea/resourcemanager/scheduler.py
   trunk/src/haizea/resourcemanager/slottable.py
Log:
* Multiple changes to slottable to improve performance of simulations
* Keep better track of resource utilization
* Added an "override-memory" option to the config file to override the memory requested in a trace file. This is useful when running simulations where the memory is one of the variables. This should be replaced with a more general mechanism eventually.

Modified: trunk/src/haizea/resourcemanager/datastruct.py
===================================================================
--- trunk/src/haizea/resourcemanager/datastruct.py	2008-11-12 00:59:08 UTC (rev 542)
+++ trunk/src/haizea/resourcemanager/datastruct.py	2008-11-20 00:29:39 UTC (rev 543)
@@ -367,6 +367,12 @@
         else:
             self.prematureend = None 
 
+    def get_final_end(self):
+        if len(self.post_rrs) == 0:
+            return self.end
+        else:
+            return self.post_rrs[-1].end
+
     def is_suspending(self):
         return len(self.post_rrs) > 0 and isinstance(self.post_rrs[0], SuspensionResourceReservation)
 

Modified: trunk/src/haizea/resourcemanager/rm.py
===================================================================
--- trunk/src/haizea/resourcemanager/rm.py	2008-11-12 00:59:08 UTC (rev 542)
+++ trunk/src/haizea/resourcemanager/rm.py	2008-11-20 00:29:39 UTC (rev 543)
@@ -289,6 +289,7 @@
         self.accounting.create_counter(constants.COUNTER_QUEUESIZE, constants.AVERAGE_TIMEWEIGHTED)
         self.accounting.create_counter(constants.COUNTER_DISKUSAGE, constants.AVERAGE_NONE)
         self.accounting.create_counter(constants.COUNTER_CPUUTILIZATION, constants.AVERAGE_TIMEWEIGHTED)
+        self.accounting.create_counter(constants.COUNTER_UTILIZATION, constants.AVERAGE_NONE)
         
         if self.daemon:
             self.daemonize()
@@ -304,7 +305,7 @@
         
         # Stop collecting data (this finalizes counters)
         self.accounting.stop()
-
+        
         # TODO: When gracefully stopping mid-scheduling, we need to figure out what to
         #       do with leases that are still running.
 
@@ -630,7 +631,7 @@
         besteffort = self.rm.scheduler.leases.get_leases(type = BestEffortLease)
         pendingbesteffort = [r for r in tracefrontend.requests if isinstance(r, BestEffortLease)]
         if stopwhen == constants.STOPWHEN_BEDONE:
-            if self.rm.scheduler.isQueueEmpty() and len(besteffort) + len(pendingbesteffort) == 0:
+            if self.rm.scheduler.is_queue_empty() and len(besteffort) + len(pendingbesteffort) == 0:
                 done = True
         elif stopwhen == constants.STOPWHEN_BESUBMITTED:
             if len(pendingbesteffort) == 0:

Modified: trunk/src/haizea/resourcemanager/scheduler.py
===================================================================
--- trunk/src/haizea/resourcemanager/scheduler.py	2008-11-12 00:59:08 UTC (rev 542)
+++ trunk/src/haizea/resourcemanager/scheduler.py	2008-11-20 00:29:39 UTC (rev 543)
@@ -184,8 +184,13 @@
         for rr in starting:
             self.handlers[type(rr)].on_start(self, rr.lease, rr)
 
-        util = self.slottable.getUtilization(nowtime)
-        get_accounting().append_stat(constants.COUNTER_CPUUTILIZATION, util)        
+        util = self.slottable.get_utilization(nowtime)
+        if not util.has_key(VMResourceReservation):
+            cpuutil = 0.0
+        else:
+            cpuutil = util[VMResourceReservation]
+        get_accounting().append_stat(constants.COUNTER_CPUUTILIZATION, cpuutil)        
+        get_accounting().append_stat(constants.COUNTER_UTILIZATION, util)        
         
     def register_handler(self, type, on_start, on_end):
         handler = ReservationEventHandler(on_start=on_start, on_end=on_end)
@@ -655,7 +660,8 @@
         # (otherwise, we only allow the VMs to start "now", accounting
         #  for the fact that vm images will have to be deployed)
         if allow_reservation_in_future:
-            futurecp = self.slottable.findChangePointsAfter(changepoints[-1][0])
+            res = self.slottable.get_reservations_ending_after(changepoints[-1][0])
+            futurecp = [r.get_final_end() for r in res if isinstance(r, VMResourceReservation)]
             futurecp = [(p,None) for p in futurecp]
         else:
             futurecp = []
@@ -838,10 +844,10 @@
                 
                 if direction == constants.DIRECTION_FORWARD:
                     t += op_time
-                    times.append((t_prev, t, {pnode:vnode}))
+                    times.append((t_prev, t, {pnode:[vnode]}))
                 elif direction == constants.DIRECTION_BACKWARD:
                     t -= op_time
-                    times.append((t, t_prev, {pnode:vnode}))
+                    times.append((t, t_prev, {pnode:[vnode]}))
 
         elif exclusion == constants.SUSPRES_EXCLUSION_LOCAL:
             # Local exclusion (which represents, e.g., reading the memory image files
@@ -1253,11 +1259,11 @@
         nodes = set(mustpreempt.keys())
         
         reservationsAtStart = self.slottable.getReservationsAt(startTime)
-        reservationsAtStart = [r for r in reservationsAtStart if r.is_preemptible()
+        reservationsAtStart = [r for r in reservationsAtStart if isinstance(r, VMResourceReservation) and r.is_preemptible()
                         and len(set(r.resources_in_pnode.keys()) & nodes)>0]
         
         reservationsAtMiddle = self.slottable.get_reservations_starting_between(startTime, endTime)
-        reservationsAtMiddle = [r for r in reservationsAtMiddle if r.is_preemptible()
+        reservationsAtMiddle = [r for r in reservationsAtMiddle if isinstance(r, VMResourceReservation) and r.is_preemptible()
                         and len(set(r.resources_in_pnode.keys()) & nodes)>0]
         
         reservationsAtStart.sort(comparepreemptability)

Modified: trunk/src/haizea/resourcemanager/slottable.py
===================================================================
--- trunk/src/haizea/resourcemanager/slottable.py	2008-11-12 00:59:08 UTC (rev 542)
+++ trunk/src/haizea/resourcemanager/slottable.py	2008-11-20 00:29:39 UTC (rev 543)
@@ -34,7 +34,10 @@
 class Node(object):
     def __init__(self, capacity, capacitywithpreemption, resourcepoolnode):
         self.capacity = ds.ResourceTuple.copy(capacity)
-        self.capacitywithpreemption = ds.ResourceTuple.copy(capacitywithpreemption)
+        if capacitywithpreemption == None:
+            self.capacitywithpreemption = None
+        else:
+            self.capacitywithpreemption = ds.ResourceTuple.copy(capacitywithpreemption)
         self.resourcepoolnode = resourcepoolnode
         
     @classmethod
@@ -57,14 +60,7 @@
         for n in self.nodelist:
             nodelist.add(Node(n.capacity, n.capacitywithpreemption, n.resourcepoolnode))
         return nodelist
-
-    def toPairList(self, onlynodes=None):
-        nodelist = []
-        for i, n in enumerate(self.nodelist):
-            if onlynodes == None or (onlynodes != None and i+1 in onlynodes):
-                nodelist.append((i+1,Node(n.capacity, n.capacitywithpreemption, n.resourcepoolnode)))
-        return nodelist
-    
+   
     def toDict(self):
         nodelist = self.copy()
         return dict([(i+1, v) for i, v in enumerate(nodelist)])
@@ -102,47 +98,76 @@
         self.changepointcache = None
         
     def getAvailabilityCacheMiss(self, time):
-        nodes = self.nodes.copy()
+        allnodes = set([i+1 for i in range(len(self.nodes.nodelist))])
+        onlynodes = None       
+        nodes = {} 
         reservations = self.getReservationsAt(time)
         # Find how much resources are available on each node
+        canpreempt = True
         for r in reservations:
             for node in r.resources_in_pnode:
-                nodes[node].capacity.decr(r.resources_in_pnode[node])
-                if not r.is_preemptible():
-                    nodes[node].capacitywithpreemption.decr(r.resources_in_pnode[node])                        
+                if onlynodes == None or (onlynodes != None and node in onlynodes):
+                    if not nodes.has_key(node):
+                        n = self.nodes[node]
+                        if canpreempt:
+                            nodes[node] = Node(n.capacity, n.capacitywithpreemption, n.resourcepoolnode)
+                        else:
+                            nodes[node] = Node(n.capacity, None, n.resourcepoolnode)
+                    nodes[node].capacity.decr(r.resources_in_pnode[node])
+                    if canpreempt and not r.is_preemptible:
+                        nodes[node].capacitywithpreemption.decr(r.resources_in_pnode[node])
+
+        # For the remaining nodes, use a reference to the original node, not a copy
+        if onlynodes == None:
+            missing = allnodes - set(nodes.keys())
+        else:
+            missing = onlynodes - set(nodes.keys())
             
+        for node in missing:
+            nodes[node] = self.nodes[node]                    
+            
         self.availabilitycache[time] = nodes
 
-    def getAvailability(self, time, resreq=None, onlynodes=None):
+    def getAvailability(self, time, resreq=None, onlynodes=None, canpreempt=False):
         if not self.availabilitycache.has_key(time):
             self.getAvailabilityCacheMiss(time)
             # Cache miss
             
+        nodes = self.availabilitycache[time]
+
         if onlynodes != None:
             onlynodes = set(onlynodes)
-            
-        nodes = self.availabilitycache[time].toPairList(onlynodes)
-        #nodes = {}
-        #for n in self.availabilitycache[time]:
-        #    nodes[n] = Node(self.availabilitycache[time][n].capacity.res, self.availabilitycache[time][n].capacitywithpreemption.res)
+            nodes = dict([(n,node) for n,node in nodes.items() if n in onlynodes])
 
         # Keep only those nodes with enough resources
         if resreq != None:
-            newnodes = []
-            for i, node in nodes:
-                if not resreq.fits_in(node.capacity) and not resreq.fits_in(node.capacitywithpreemption):
+            newnodes = {}
+            for n, node in nodes.items():
+                if not resreq.fits_in(node.capacity) or (canpreempt and not resreq.fits_in(node.capacitywithpreemption)):
                     pass
                 else:
-                    newnodes.append((i, node))
+                    newnodes[n]=node
             nodes = newnodes
-        
-        return dict(nodes)
+
+        return nodes
     
-    def getUtilization(self, time, restype=constants.RES_CPU):
-        nodes = self.getAvailability(time)
-        total = sum([n.capacity.get_by_type(restype) for n in self.nodes.nodelist])
-        avail = sum([n.capacity.get_by_type(restype) for n in nodes.values()])
-        return 1.0 - (float(avail)/total)
+    def get_utilization(self, time):
+        total = sum([n.capacity.get_by_type(constants.RES_CPU) for n in self.nodes.nodelist])
+        util = {}
+        reservations = self.getReservationsAt(time)
+        for r in reservations:
+            for node in r.resources_in_pnode:
+                if isinstance(r, ds.VMResourceReservation):
+                    use = r.resources_in_pnode[node].get_by_type(constants.RES_CPU)
+                    util[type(r)] = use + util.setdefault(type(r),0.0)
+                elif isinstance(r, ds.SuspensionResourceReservation) or isinstance(r, ds.ResumptionResourceReservation) or isinstance(r, ds.ShutdownResourceReservation):
+                    use = r.vmrr.resources_in_pnode[node].get_by_type(constants.RES_CPU)
+                    util[type(r)] = use + util.setdefault(type(r),0.0)
+        util[None] = total - sum(util.values())
+        for k in util:
+            util[k] /= total
+            
+        return util
 
     def getReservationsAt(self, time):
         item = KeyValueWrapper(time, None)
@@ -167,6 +192,12 @@
         res = [x.value for x in self.reservationsByStart[startpos:]]
         return res
 
+    def get_reservations_ending_after(self, end):
+        startitem = KeyValueWrapper(end, None)
+        startpos = bisect.bisect_left(self.reservationsByEnd, startitem)
+        res = [x.value for x in self.reservationsByEnd[startpos:]]
+        return res
+
     def get_reservations_ending_between(self, start, end):
         startitem = KeyValueWrapper(start, None)
         enditem = KeyValueWrapper(end, None)
@@ -362,12 +393,10 @@
         self.time = time
         self.resreq = resreq
         self.onlynodes = onlynodes
-
         self.avail = {}
 
         # Availability at initial time
-        availatstart = self.slottable.getAvailability(self.time, self.resreq, self.onlynodes)
-
+        availatstart = self.slottable.getAvailability(self.time, self.resreq, self.onlynodes, canpreempt)
         for node in availatstart:
             capacity = availatstart[node].capacity
             if canpreempt:
@@ -380,7 +409,7 @@
         nodes = set(availatstart.keys())
         changepoints = self.slottable.findChangePointsAfter(self.time, nodes=self.avail.keys())
         for p in changepoints:
-            availatpoint = self.slottable.getAvailability(p, self.resreq, nodes)
+            availatpoint = self.slottable.getAvailability(p, self.resreq, nodes, canpreempt)
             newnodes = set(availatpoint.keys())
             
             # Add entries for nodes that have no resources available



More information about the Haizea-commit mailing list