The M/M/n queue is a discrete stochastic process that models a queue with n servers. There are three parameters:
\(n\): the number of servers
\(\lambda\): the arrival rate of customers
\(\mu\): the service rate of each server
The “M” in M/M/n stands for “memoryless” or Markovian. The M/M/n queue models the following process: - customers arrive at the queue according to a Poisson process with rate \(\lambda\). - Each customer is served by one of the n servers, and the service times are exponentially distributed with rate \(\mu\). - If all servers are busy, the customer waits in line until a server becomes available.
We are interested in testing the performance of the queue as function of the three parameters. There are various performance measures we can compute, including: - The average number of customers in the waiting line - The average time a customer spends waiting in line - The usage of the servers - The probability that a customer has to wait in line
There are two approaches we can take to simulate an M/M/n queue
Process driven
Event driven
VM =window.VMvmTheme = Generators.observe(notify => VM.plotting.onThemeChange(notify))chartColors = VM.plotting.colors(vmTheme)mmnQueuePlot = VM.plotting.persistentPlot({height:"340px"})// Discrete-event simulation of an M/M/n queue until maxCustomers have// departed. Events are kept in a list sorted by time (a heap would be// faster; a thousand customers don't need one). Returns each customer's// arrival, service-start and departure times and the queue length after// every event.functionmmnSimulate({arrivalRate, serviceRate, servers, maxCustomers, seed}) {const rng = VM.sampling.seededRandom(seed)const interArrival = VM.sampling.exponentialRandom(rng, arrivalRate)const serviceTime = VM.sampling.exponentialRandom(rng, serviceRate)const events = []functionschedule(time, type, id) {let k = events.lengthwhile (k >0&& events[k -1].time> time) k-- events.splice(k,0, {time, type, id}) }const arrival = [], start = [], departure = []const waiting = []const log = {times: [],lengths: []}let busy =0let departed =0let nextId =1schedule(interArrival(),"arrival",0)while (events.length>0&& departed < maxCustomers) {constevent= events.shift()const clock =event.time log.times.push(clock) log.lengths.push(waiting.length)if (event.type==="arrival") { arrival[event.id] = clockif (busy < servers) { busy++ start[event.id] = clockschedule(clock +serviceTime(),"departure",event.id) } else { waiting.push(event.id) }if (nextId < maxCustomers) {schedule(clock +interArrival(),"arrival", nextId) nextId++ } } else { departure[event.id] = clock departed++ busy--if (waiting.length>0) {const next = waiting.shift() busy++ start[next] = clockschedule(clock +serviceTime(),"departure", next) } } }return {arrivalRate, serviceRate, servers, arrival, start, departure, log}}