Skip to content

A M/M/1 and M/M/1/K computer networking queue simulator, built in C++, that looks at the effects of traffic intensity on the performance of the simulators (with respect to the average number of packets in the system, the proportion of time the system is idle, and the probability of dropping a packet).

Notifications You must be signed in to change notification settings

thanujann/Queue-Simulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

To run the simulator, simply run "make" in the command terminal.

M/M/1 Queue Simulator

The global variables needed for the simulator include the size of the temporary arrays that will be used to load the queues (defaultSize), the three event queue arrays (observerQueue, arrivalQueue, departureQueue), and the counters that will be needed for the performance metrics calculations (observationCounter, arrivalCounter, departureCounter, idleCounter, numberOfPacketsInQueue). The queues used for this simulator are priority queues, where priority is given to events with earlier arrival times.

To initiate the simulation, the simulate(…) method is called. The values for T, alpha, lambda, L, and C are all parameters to this method. The first step is to reset all the global counters to 0. This is because we don’t want the performance metrics to be calculated with any old data from a previous simulation. Next, random, observer and arrival times are generated, and filled into two arrays (observerTimes and arrivalTimes). The random values have an exponential distribution and use the getExponentialRandomVariable(…) function mentioned in Question 1 above.

Next, the observer and arrival events get generated by calling the generateObserverAndArrivalEvents(…) method and passing in T, observerTimes, arrivalTimes, alpha, and lambda, as parameters. The method declares two counters (observerTimeCounter and arrivalTimeCounter) and uses these counters to populate the observer and arrival queues with events. While each counter is less than the simulation time, T, the global observer and arrival queues get updated with a new event. A new event is created (using the Event class in Event.cpp and Event.h) by specifying the type of event (observer or arrival) and the time that this event occurs at (the counters). This method also includes a section where the observerTimes and arrivalTimes arrays get reset. This is so that if the simulation time, T, is sufficiently long enough, then the counters won’t run out of random values to increment themselves by.

After the observer and arrival events have been generated, the simulator needs to handle these events. The simulate(…) method includes a while loop that does this event handling. While any of the three global queues (observerQueue, arrivalQueue, or departureQueue) are not empty, the simulator will continue to handle each event. To find the next event, the simulator calls the getNextEvent() method. This method simply looks at the first event in all three of the queues and returns the earliest event. This is done through a series of conditional statements to compare the first event in each queue. The earliest event of the three queues will be returned from the getNextEvent() method.

Once the next event is found, the simulator checks it’s type (with the getType() method specified in the Event class), and determines which handler method needs to be called. If it’s an observer event, then the handleObserverEvent method would be called. This method first increments the observationCounter global variable and pops the first event off the front of the observer queue. Then, if there are no events in the departure queue (indicating that all events have been serviced), then the global idleCounter variable is incremented. Alternatively, if the departure queue is not empty, then the global numberOfPacketsInQueue variable gets incremented by the size of the queue. If the next event found is an arrival event, then the handleArrivalEvent(…) method is called. This method takes L, C, and the event as parameters. Like the previous handler, the arrival handler first increments the global arrivalCounter variable, and pops the first event off the arrival queue. Next, it needs to create a corresponding departure event for this arrival event. First, it simulates the service time of the event by generating an exponential random variable with parameter 1/L and then dividing this random value by C. Then, if the departure queue is empty, the departure time of the new departure event would be the current event’s service time plus it’s arrival time. Alternatively, if the departure queue isn’t empty, then the departure time of the departure event would be the current event’s service time plus the departure time of the last event in the departure queue. This departure time is then used to create a new event object which is pushed onto the departure queue. If the next event found is a departure event, then the handleDepartureEvent() method is called. This method simply increments the global departureCounter variable and pops the first event off the departure queue.

Once the three queues are empty, the simulator would be completed handling all events, and the global counters would all be populated with the correct data. Now, this data can be used to calculate the performance metrics of the simulator. The two metrics that we are interested in are the average number of packets in the queue, E[N], and the proportion of time the system is idle, Pidle. For calculating E[N], the numberOfPacketsInQueue variable is divided by the observationCounter. This is because the numberOfPacketsInQueue variable is updated for every observer event, as mentioned earlier. This means that every time an observer event sees a non-empty departure queue, it adds to the total sum of packets waiting in the queue. This represents the total sum of the number of packets in the queue for different moments in the simulation, namely, every time there is an observer event. To get the average number of packets, this sum simply needs to be divided by the observationCounter, which is the number of observation events that were processed. Thus, this division gives the average number of packets in the queue throughout the simulation, E[N]. For calculating Pidle, the idleCounter variable is divided by the observationCounter. The idleCounter represents the number of observer events that the departure queue is empty for. Like the calculation of E[N], if we simply divide the idleCounter by the observationCounter, then it will result in the proportion of time the system is idle, Pidle.

M/M/1/K Queue Simulator

To handle a M/M/1/K queue, the only changes needed were to update the arrival event handler, handleArrivalEvent(…) and add another global counter called droppedPacketsCounter. This global variable was also set to 0 at the beginning of the simulate(…) method, like the other global counters. The piece of code added was the if statement checking if the departure queue size is less than the queue capacity, K. Every time an arrival event is being handled, it does this comparison. If the departure queue size is less than K, then the packet is accepted, and a corresponding departure event is created and added to the departure queue. However, if the departure queue size is greater than or equal to K, then the packet is dropped and the global droppedPacketsCounter variable is incremented.

About

A M/M/1 and M/M/1/K computer networking queue simulator, built in C++, that looks at the effects of traffic intensity on the performance of the simulators (with respect to the average number of packets in the system, the proportion of time the system is idle, and the probability of dropping a packet).

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published