[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