#include <iostream> #include <random> #include <cmath> #include <algorithm> #include <cstdlib> #include <vector> #include <queue> using namespace std; struct Process { int pid; double arrival_time; double service_time; }; struct Event { int type; double time; Event* nextEvent; }; double exponential(double lambda) // Generate Exponential Random Variable { double u = (rand() + 1.0) / (RAND_MAX + 1.0); // Add 1 to avoid division by zero double exp = -log(u) / lambda; // Calculate - ln(U) / lambda return exp; } void sched_event(int type, double time, Event*& eq_head) { Event* e = new Event{type, time, nullptr}; if (!eq_head || time < eq_head->time) { e->nextEvent = eq_head; eq_head = e; } else { Event* cur = eq_head; while (cur->nextEvent && cur->nextEvent->time <= time) { cur = cur->nextEvent; } e->nextEvent = cur->nextEvent; cur->nextEvent = e; } } void simulate(int arrival, double service) { cout << "Simulation for lambda = " << arrival << '\n'; double time = 0; int completedProc = 0; bool serverIdle = true; int readyQueueCount = 0; Event* eq_head = NULL; sched_event(0, exponential(arrival), eq_head); // Performance Metrics and helper variables double total_turnaround_time = 0; double total_throughput = 0; double untilization = 0; double avg_proc_rdy_q = 0; double busyTime; double totalBusy = 0; double areaQueue = 0; queue<double> arrivals; // arrival queue to maintain arrival times while (completedProc < 10000) { Event* e = eq_head; eq_head = eq_head->nextEvent; double old_clock = time; time = e->time; areaQueue += readyQueueCount * (time - old_clock); switch (e->type) { case 0: { arrivals.push(time); sched_event(0,time+exponential(arrival),eq_head); if (serverIdle) { serverIdle = false; busyTime = time; sched_event(1,time+exponential(1.0/service),eq_head); } else { readyQueueCount++; } break; } case 1: { total_turnaround_time+= time - arrivals.front(); arrivals.pop(); completedProc++; if (readyQueueCount == 0) { serverIdle = true; totalBusy += time - busyTime; } else { readyQueueCount--; sched_event(1,time+exponential(1.0/service),eq_head); } break; } } delete(e); } if (readyQueueCount > 0) // if CPU is busy as when 10000th process is completed // appropriately calculate busyTime { totalBusy += time - busyTime; } cout << "Average Turnaround Time: " << total_turnaround_time / 10000.0 << '\n'; cout << "Throughput: " << 10000.0 / time << '\n'; cout << "CPU Utilization: " << totalBusy / time << '\n'; cout << "Average # Processes in Ready Queue: " << areaQueue / time << '\n'; } int main() { // do 21 runs from lambda = 10 to lambda = 30 int lambda = 10; double SERVICE_TIME = 0.04; while (lambda <= 30) { simulate(lambda,SERVICE_TIME); lambda++; } }
Standard input is empty
Simulation for lambda = 10 Average Turnaround Time: 0.0653848 Throughput: 9.88683 CPU Utilization: 0.399048 Average # Processes in Ready Queue: 0.247417 Simulation for lambda = 11 Average Turnaround Time: 0.0710845 Throughput: 11.0452 CPU Utilization: 0.441521 Average # Processes in Ready Queue: 0.34362 Simulation for lambda = 12 Average Turnaround Time: 0.0808757 Throughput: 12.0362 CPU Utilization: 0.485066 Average # Processes in Ready Queue: 0.488367 Simulation for lambda = 13 Average Turnaround Time: 0.0839423 Throughput: 13.182 CPU Utilization: 0.516749 Average # Processes in Ready Queue: 0.5903 Simulation for lambda = 14 Average Turnaround Time: 0.0913539 Throughput: 14.0472 CPU Utilization: 0.565097 Average # Processes in Ready Queue: 0.718169 Simulation for lambda = 15 Average Turnaround Time: 0.0990062 Throughput: 15.1167 CPU Utilization: 0.607872 Average # Processes in Ready Queue: 0.888777 Simulation for lambda = 16 Average Turnaround Time: 0.114309 Throughput: 16.0893 CPU Utilization: 0.644629 Average # Processes in Ready Queue: 1.19426 Simulation for lambda = 17 Average Turnaround Time: 0.1142 Throughput: 17.0614 CPU Utilization: 0.668112 Average # Processes in Ready Queue: 1.28041 Simulation for lambda = 18 Average Turnaround Time: 0.141253 Throughput: 17.9936 CPU Utilization: 0.720111 Average # Processes in Ready Queue: 1.82169 Simulation for lambda = 19 Average Turnaround Time: 0.149392 Throughput: 18.8085 CPU Utilization: 0.747595 Average # Processes in Ready Queue: 2.06226 Simulation for lambda = 20 Average Turnaround Time: 0.223565 Throughput: 19.9875 CPU Utilization: 0.811574 Average # Processes in Ready Queue: 3.65694 Simulation for lambda = 21 Average Turnaround Time: 0.223172 Throughput: 21.0069 CPU Utilization: 0.830976 Average # Processes in Ready Queue: 3.8593 Simulation for lambda = 22 Average Turnaround Time: 0.375457 Throughput: 22.2391 CPU Utilization: 0.882417 Average # Processes in Ready Queue: 7.46565 Simulation for lambda = 23 Average Turnaround Time: 0.439256 Throughput: 23.2318 CPU Utilization: 0.930982 Average # Processes in Ready Queue: 9.28689 Simulation for lambda = 24 Average Turnaround Time: 0.994166 Throughput: 24.291 CPU Utilization: 0.974773 Average # Processes in Ready Queue: 23.1735 Simulation for lambda = 25 Average Turnaround Time: 3.64644 Throughput: 25.0752 CPU Utilization: 0.997018 Average # Processes in Ready Queue: 90.9795 Simulation for lambda = 26 Average Turnaround Time: 10.7003 Throughput: 25.0888 CPU Utilization: 0.998663 Average # Processes in Ready Queue: 276.469 Simulation for lambda = 27 Average Turnaround Time: 15.9446 Throughput: 25.2471 CPU Utilization: 0.999746 Average # Processes in Ready Queue: 430.587 Simulation for lambda = 28 Average Turnaround Time: 22.7517 Throughput: 24.8335 CPU Utilization: 0.998479 Average # Processes in Ready Queue: 624.268 Simulation for lambda = 29 Average Turnaround Time: 29.0778 Throughput: 24.8417 CPU Utilization: 0.999241 Average # Processes in Ready Queue: 838.319 Simulation for lambda = 30 Average Turnaround Time: 32.7579 Throughput: 24.4694 CPU Utilization: 0.999444 Average # Processes in Ready Queue: 985.825