Ejemplo n.º 1
0
class Source(Model):
    """Source module represents the traffic source with exponential intervals.

    Connections: queue

    Handlers:
    - handle_timeout(): called upon next arrival timeout

    Statistics:
    - intervals: `Intervals`, stores a set of inter-arrival intervals

    Parent: `QueueingSystem`
    """
    def __init__(self, sim, arrival, index):
        super().__init__(sim)
        self.arrival = arrival
        self.index = index

        # Statistics:
        self.intervals = Intervals()
        self.num_generated = 0
        self.delays = Statistic()

        # Initialize:
        self._schedule_next_arrival()

    def handle_timeout(self):
        packet = Packet(self, self.sim.stime)
        self.connections['queue'].send(packet)
        self._schedule_next_arrival()
        self.num_generated += 1

    def _schedule_next_arrival(self):
        self.intervals.record(self.sim.stime)
        self.sim.schedule(self.arrival(), self.handle_timeout)
Ejemplo n.º 2
0
class Source(Model):
    """Source module represents the traffic source with exponential intervals.

    Connections: queue

    Handlers:
    - on_timeout(): called upon next arrival timeout

    Statistics:
    - intervals: `Intervals`, stores a set of inter-arrival intervals

    Parent: `QueueingSystem`
    """
    def __init__(self, sim, arrival_mean):
        super().__init__(sim)
        self.__arrival_mean = arrival_mean
        # Statistics:
        self.intervals = Intervals()
        # Initialize:
        self._schedule_next_arrival()

    @property
    def arrival_mean(self):
        return self.__arrival_mean

    def on_timeout(self):
        queue = self.connections['queue'].module
        queue.push()
        self._schedule_next_arrival()
    
    def _schedule_next_arrival(self):
        self.intervals.record(self.sim.stime)
        self.sim.schedule(exponential(self.arrival_mean), self.on_timeout)
Ejemplo n.º 3
0
def test_record_valid_data():
    ints = Intervals()
    assert ints.as_tuple() == ()

    ints.record(2)
    assert_almost_equal(ints.as_tuple(), (2, ))

    ints.record(3.4)
    assert_almost_equal(ints.as_tuple(), (2, 1.4))
Ejemplo n.º 4
0
class Sink(Model):
    """Sink module represents the traffic sink and counts arrived packets.

    Methods:
    - receive_packet(): called when the server finishes serving packet.
    """
    def __init__(self, sim):
        super().__init__(sim)
        # Statistics:
        self.departures = Intervals()
        self.departures.record(self.sim.stime)
    
    def receive_packet(self):
        self.departures.record(self.sim.stime)
Ejemplo n.º 5
0
class Sink(Model):
    """Sink module represents the traffic sink and counts arrived packets.

    Methods:
    - receive_packet(): called when the server finishes serving packet.
    """
    def __init__(self, sim):
        super().__init__(sim)
        # Statistics:
        self.arrival_intervals = Intervals()
        self.arrival_intervals.record(self.sim.stime)

    def handle_message(self, message, connection=None, sender=None):
        assert isinstance(message, Packet)
        self.arrival_intervals.record(self.sim.stime)
        message.source.delays.append(self.sim.stime - message.created_at)
Ejemplo n.º 6
0
def test_record_illegal_types_raises_error(value):
    ints = Intervals()
    with pytest.raises(TypeError) as excinfo:
        ints.record(value)
    assert 'only numeric values expected' in str(excinfo.value).lower()
Ejemplo n.º 7
0
def test_record_in_past_raises_error():
    ints = Intervals([10])
    with pytest.raises(ValueError) as excinfo:
        ints.record(9.9)
    assert 'prohibited timestamps from past' in str(excinfo.value).lower()
Ejemplo n.º 8
0
def test_intervals_copy_list_content_instead_of_pointer():
    data = [1, 2]
    ints = Intervals(data)
    ints.record(3)
    assert ints.as_tuple() == (1, 1, 1)
    assert data == [1, 2]
Ejemplo n.º 9
0
class Server(Model):
    """Server module represents a packet server with exponential service time.

    Connections: queue, sink

    Handlers:
    - on_service_end(): called upon service timeout

    Methods:
    - start_service(): start new packet service; generate error if busy.

    Statistics:
    - delays: `Statistic`, stores a set of service intervals
    - busy_trace: `Trace`, stores a vector of server busy status
    - num_served: `int`

    Parent: `QueueingSystem`
    """
    def __init__(self, sim, service_time, index=0):
        super().__init__(sim)
        self.service_time = service_time
        self.packet = None
        self.index = index

        # Statistics:
        self.service_intervals = Statistic()
        self.busy_trace = Trace()
        self.busy_trace.record(self.sim.stime, 0)
        self.departure_intervals = Intervals()
        self.departure_intervals.record(sim.stime)
        self.num_served = 0

    @property
    def busy(self):
        return self.packet is not None

    @property
    def ready(self):
        return self.packet is None

    def handle_service_end(self):
        assert self.busy
        stime = self.sim.stime

        self.connections['next'].send(self.packet)
        self.parent.add_system_wait_interval(stime - self.packet.arrived_at,
                                             self.index)

        self.packet = None

        self.busy_trace.record(stime, 0)
        self.departure_intervals.record(stime)
        self.num_served += 1

        # Requesting next packet from the queue:
        queue = self.connections['queue'].module
        if queue.size > 0:
            self.serve(queue.pop())

        self.parent.update_system_size(self.index)

    def _start_service(self):
        delay = self.service_time()
        self.sim.schedule(delay, self.handle_service_end)
        return delay

    def serve(self, packet):
        assert not self.busy
        self.packet = packet
        delay = self._start_service()
        self.service_intervals.append(delay)
        self.busy_trace.record(self.sim.stime, 1)
Ejemplo n.º 10
0
class Queue(Model):
    """Queue module represents the packets queue, stores only current size.

    Connections: server

    Methods and properties:
    - push(): increase the queue size
    - pop(): decrease the queue size
    - size: get current queue size

    Statistics:
    - size_trace: Trace, holding the history of the queue size updates
    - num_arrived: `int`
    - num_dropped: `int`
    - drop_ratio: `float`
    """
    def __init__(self, sim, capacity, index=0):
        super().__init__(sim)
        self.__capacity = capacity
        self.packets = deque()
        self.index = index
        # Statistics:
        self.size_trace = Trace()
        self.size_trace.record(self.sim.stime, 0)
        self.num_dropped = 0
        self.arrival_intervals = Intervals()
        self.arrival_intervals.record(sim.stime)
        self.num_arrived = 0
        self.wait_intervals = Statistic()

    @property
    def capacity(self):
        return self.__capacity

    @property
    def size(self):
        return len(self.packets)

    @property
    def drop_ratio(self):
        if self.num_arrived == 0:
            return 0
        return self.num_dropped / self.num_arrived

    def handle_message(self, message, connection=None, sender=None):
        self.push(message)

    def push(self, packet):
        self.arrival_intervals.record(self.sim.stime)
        self.num_arrived += 1
        server = self.connections['server'].module

        packet.arrived_at = self.sim.stime

        if self.size == 0 and not server.busy:
            server.serve(packet)
            self.wait_intervals.append(self.sim.stime - packet.arrived_at)

        elif self.capacity is None or self.size < self.capacity:
            self.packets.append(packet)
            self.size_trace.record(self.sim.stime, self.size)

        else:
            self.num_dropped += 1

        self.parent.update_system_size(self.index)

    def pop(self):
        packet = self.packets.popleft()
        self.size_trace.record(self.sim.stime, self.size)
        self.wait_intervals.append(self.sim.stime - packet.arrived_at)
        return packet

    def __str__(self):
        return f'Queue({self.size})'