Commit ccb3d969 authored by S. Lackner's avatar S. Lackner

[sched] Increase performance by returning collection objects as immutable list views

parent addc20e1
......@@ -7,6 +7,7 @@
import sys
from .resource import Resources, Resource
from .utils import ListView
class Allocation:
......@@ -35,11 +36,11 @@ class Allocation:
self._end_time = None
self._walltime = walltime
if isinstance(resources, (list, tuple, Resources)):
if isinstance(resources, Resource):
self.add_resource(resources)
else: # Assume some kind of list type
for r in resources:
self.add_resource(r)
elif isinstance(resources, Resource):
self.add_resource(resources)
if job is not None:
if walltime is None:
......@@ -54,7 +55,7 @@ class Allocation:
@property
def resources(self):
"""The list of assigned resources."""
return tuple(self._resources)
return ListView(self._resources)
@property
def allocated(self):
......@@ -92,7 +93,7 @@ class Allocation:
@property
def allocated_resources(self):
"""The list of allocated resources (currently assigned as computing)."""
return tuple(self._allocated_resources)
return ListView(self._allocated_resources)
@property
def previously_allocated(self):
......@@ -212,7 +213,7 @@ class Allocation:
def remove_all_resources(self):
"""Removes all resources from this allocation."""
assert not self.allocated and not self.previously_allocated, "Allocation is in invalid state"
for r in self._resources[:]:
for r in self._resources.copy():
self.remove_resource(r)
def allocate(self, scheduler, range1, *more_ranges):
......@@ -258,7 +259,7 @@ class Allocation:
self.remove_all_resources()
return
for r in self.resources:
for r in self.resources.copy():
r._do_free_allocation(self)
self._end_time = self._scheduler.time
......
......@@ -8,7 +8,7 @@
"""
from batsim.batsim import Job as BatsimJob, Batsim
from .utils import ObserveList, filter_list
from .utils import ObserveList, filter_list, ListView
from .alloc import Allocation
from .messages import MessageBuffer
from .profiles import Profiles
......@@ -117,7 +117,7 @@ class Job:
They are either given in the workload through the custom `deps` field of a job
or added by the scheduler as manual dependencies.
"""
return tuple(
return ListView(
self.get_job_data("deps", []) +
self._own_dependencies)
......@@ -302,7 +302,7 @@ class Job:
result.append(dep_job)
except KeyError:
result.append(dep)
return tuple(result)
return ListView(result)
def free(self):
"""Free the current allocation of this job."""
......
......@@ -7,7 +7,7 @@
"""
from enum import Enum
from .utils import ObserveList, filter_list
from .utils import ObserveList, filter_list, ListView
class Resource:
......@@ -72,7 +72,7 @@ class Resource:
@property
def allocations(self):
"""A copy of the allocations (current and future) where this resource is part of."""
return tuple(self._allocations)
return ListView(self._allocations)
@property
def computing(self):
......
......@@ -18,6 +18,7 @@ from .job import Job, Jobs
from .reply import ConsumedEnergyReply
from .utils import DictWrapper
from .messages import Message
from .utils import ListView
class BaseBatsimScheduler(BatsimScheduler):
......@@ -281,8 +282,8 @@ class Scheduler(metaclass=ABCMeta):
@property
def events(self):
"""The events happened in the scheduler (`tuple`)"""
return tuple(self._events)
"""The events happened in the scheduler."""
return ListView(self._events)
@property
def hpst(self):
......@@ -555,7 +556,7 @@ def as_scheduler(*args, on_init=[], on_end=[], base_classes=[], **kwargs):
:param kwargs: additional arguments passed to the scheduler function (in each iteration)
"""
base_classes = base_classes[:]
base_classes = base_classes.copy()
base_classes.append(Scheduler)
def convert_to_scheduler(schedule_function):
......
......@@ -21,8 +21,8 @@ class ObserveList:
@property
def data(self):
"""A copy of the content of the list."""
return tuple(self._data)
"""A view of the content of the list."""
return ListView(self._data)
def _check_new_elem(self, element):
"""Checks whether a new element should be added.
......@@ -251,3 +251,48 @@ class SafeIterList(list):
def __iter__(self):
return iter(self[:])
class ContainerView:
"""A view for various containers (e.g. sets, lists, or dicts)."""
def __init__(self, l):
self._data = l
def copy(self):
return self._data.copy()
def __getitem__(self, *args, **kwargs):
return self._data.__getitem__(*args, **kwargs)
def __len__(self, *args, **kwargs):
return self._data.__len__(*args, **kwargs)
def __contains__(self, *args, **kwargs):
return self._data.__contains__(*args, **kwargs)
def __iter__(self, *args, **kwargs):
return self._data.__iter__(*args, **kwargs)
def __add__(self, *args, **kwargs):
return self._data.__add__(*args, **kwargs)
def __str__(self, *args, **kwargs):
return self._data.__str__(*args, **kwargs)
class ListView(ContainerView):
"""A view for dictionaries."""
def index(self, *args, **kwargs):
return self._data.index(*args, **kwargs)
def count(self, x):
return self._data.count(*args, **kwargs)
class DictView(ContainerView):
"""A view for dictionaries."""
def get(self, *args, **kwargs):
return self._data.get(*args, **kwargs)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment