fieq.fikri
fieq.fikri

Reputation: 73

Simpy queue simulation

I'm trying to simulate a queue with limited buffer where no packet is dropped but kept in waiting . Bear with me since I'm just a student with basic coding skills.

The packet arrive exponentially distributed and each hold a packet size with mean 1250 bytes. I managed to get the code working for packet arrival + processing time but i couldn't make the packet 'depart' and also simulating the queue (so far, it is with unlimited buffer) Is there anything I could do to simulate the packet departure and the queue limit?

code:

import random
import simpy

RANDOM_SEED = 42
NEW_CUSTOMERS = 100  # Total number of customers
INTERVAL_CUSTOMERS = 1  # Generate new customers roughly every x seconds
SIZE = 1250

def source(env, number, interval, port):
    """Source generates packet randomly"""
    for i in range(number):
        size =  int(random.expovariate(0.0008))
        packet = Packet(env, '%d' % i, size, port, time_in_port=1)
        env.process(packet)
        t = random.expovariate(1 / interval)
        yield env.timeout(t)

def Packet(env, id, size, port, time_in_port):
    arrive = env.now
    yield Queue.buffer.put(size)
    print('packet%s %s arriving at %lf' % (id, size, arrive))

    with port.request() as req:
        yield req

        tip = random.expovariate(1/time_in_port)
        yield env.timeout(tip)
        amount = size
        yield Queue.buffer.get(amount)
        print('packet%s %s finished processing at %lf' % (id, size, env.now))

class queue:     #THIS PART WON'T WORK
    def __init__(self, env):
        self.port = simpy.Resource(env, capacity=1)
        self.buffer = simpy.Container(env, init = 0, capacity=12500)
        self.mon_proc = env.process(self.monitor_tank(env))

    def monitor_tank(self, env):
        while True:
           if self.buffer.level > 12500:
             print('Full at %d' % env.now)


random.seed(RANDOM_SEED)
env = simpy.Environment()
Queue = queue(env)

port = simpy.Resource(env, capacity=1)
env.process(source(env, NEW_CUSTOMERS, INTERVAL_CUSTOMERS, port))
env.run()

The queue class didn't work (The program won't run at all). It will run if only I remove the queue class and simulate packet arrival and processing time. Would appreciate any help to make me simulate the packet departure(using a sink) and the queue limit. Thanks.

Upvotes: 1

Views: 3241

Answers (3)

Eduardo Pécora
Eduardo Pécora

Reputation: 107

Hello I think the code will solve your problem or at least give you a direction. As in your original code all the packages have the same size, I modelled in this packages, but to change to bytes is straight forward.

I used a buffer (container) and a server (resource).

;)

import simpy
import random     

def arrival(env, buffer):
  #Arrival of the Package

  while True:
    print('Package ARRIVED at %.1f \n\t Buffer: %i' 
                      % (env.now, buffer.level))
    yield buffer.put(1) # Put the package in the buffer
    yield env.timeout(random.expovariate(1.0)) # time between arrivals
    env.process(processDeparture(env, buffer, server)) 

def processDeparture(env, buffer, server):
  #Processing and Departure of the Package

  while True:
    
    # request a Server to process thge package
    request = server.request()
    yield request

    yield buffer.get(1) # GET a package from the buffer

    # Processing time of the package
    processingTime = 2
    print('Package begin processing at %.1f'
                      % (env.now))
    yield env.timeout(processingTime)
    print('Package end processing at %.1f'
                      % (env.now))
    # release the server
    yield server.release(request)


random.seed(150)            
env = simpy.Environment()
buffer = simpy.Container(env, capacity=3, init=0)  # Create the Buffer 
server = simpy.Resource(env, capacity=1)           # Create the servers (resources)

env.process(arrival(env, buffer))         

env.run(until=30)                                # Execute the Model

Upvotes: 0

Michael
Michael

Reputation: 1914

I think this code from your code is a infinite loop and is blocking your code from running

def monitor_tank(self, env):
        while True:
           if self.buffer.level > 12500:
             print('Full at %d' % env.now)

Try commenting This piece out, or adding a env.timeout so it "sleeps" for a bit on every loop pass

Upvotes: 1

sfjac
sfjac

Reputation: 7284

Not familiar with the details, but your call to self.monitor_tank(env) in the queue constructor is going to go into a tight infinite loop - it isn't a generator, just an unending loop, so python is going to get stuck at that point in the execution.

Upvotes: 2

Related Questions