A discrete-time simulation framework for studying how queue buildup, latency, throughput and scheduling behaviour change under varying system load and worker capacity.
This project models a simplified compute system in which jobs arrive over time, wait in a queue and are processed by a limited number of workers.
The simulator is designed to explore questions such as:
- How does increasing load affect queue growth and latency?
- How does worker capacity affect throughput and congestion?
- What tradeoffs appear under different scheduling policies?
- When does a system begin to saturate?
Rather than relying on real infrastructure, this project provides a lightweight experimental environment for studying system behaviour under controlled conditions.
The simulator currently includes:
- Job arrivals over time
- Finite worker capacity
- Queue growth and draining
- Variable job durations
- Latency measurement
- Throughput measurement
- Queue size history over time
- Repeatable experiments using fixed random seeds
- Scheduling policy comparison
- FIFO (first-in, first-out)
- SJF (shortest-job-first)
- What happens when arrival pressure increases?
- How many workers are needed before congestion falls sharply?
- Does a scheduling policy improve average latency at the cost of fairness?
- At what point does throughput begin to plateau while latency keeps rising?
- Discrete-time simulation loop
- Configurable worker count
- Configurable arrival probability
- Configurable queue policy
- CSV experiment output
- Matplotlib-based result plotting
- Queue-over-time visualisation
- Comparative experiment summaries
Increasing worker count reduced queue buildup and latency significantly.
Example result pattern:
- 1 worker: severe congestion, high latency
- 2 workers: much lower latency, reduced queueing
- 4 workers: very low queue depth and near-minimal latency
This demonstrated the relationship between worker capacity, queue pressure and response quality.
With a fixed worker count, increasing arrival pressure produced:
- larger queue depth
- higher average latency
- higher worst-case latency
- throughput gains that began to flatten at high load
This suggests the onset of system saturation, where additional offered load mainly increases waiting rather than productive throughput.
Under identical workload and capacity:
- SJF reduced average latency and peak queue depth
- FIFO produced lower worst-case latency
This reflects a classic systems tradeoff:
- SJF improves typical responsiveness
- FIFO is fairer to long jobs
- SJF can increase starvation risk for long-duration work
The project can generate:
- experiment summary tables
- CSV output files
- average latency plots
- throughput plots
- queue-over-time plots
- scheduling policy comparison plots
system-sim/
├── sim/
│ ├── engine.py
│ ├── job.py
│ ├── queue.py
│ └── workers.py
├── metrics/
│ └── plot_results.py
├── experiments/
├── results/
│ ├── results_summary.csv
│ ├── results_arrival_experiment.csv
│ └── *.png
├── README.md
└── run.py
Clone the repository and run:
python run.py


