Shortest Remaining Time First (Preemptive SJF) Scheduling Algorithm (original) (raw)
Last Updated : 03 Feb, 2025
In this post, we will talk about the pre-emptive version of Shortest Job First (SJF) scheduling, called **Shortest Remaining Time First (SRTF). In SRTF, the process with the least time left to finish is selected to run. The running process will continue until it finishes or a new process with a shorter remaining time arrives. This way, the process that can finish the fastest is always given priority.
**Implementation of SRTF Algorithm
**Steps:
**1. Input Process Details
- Take the number of processes and input the arrival time and burst time for each process.
2. Track Remaining Time
- Create an array for remaining times, initialized with burst times.
3. Initialize Variables
- Set the current time to 0.
- Track completed processes, waiting time, and turnaround time.
4. Check for Arriving Processes
- At each time unit, add processes with arrival time ≤ current time to the ready queue.
5. Select Shortest Remaining Time
- Pick the process with the smallest remaining time from the ready queue.
- Preempt if a new process arrives with a shorter remaining time.
6. Execute Process
- Decrease the remaining time of the selected process.
- Increment the current time.
7. Process Completion
- When remaining time reaches 0:
- Mark the process as completed.
- Calculate Turnaround Time = Completion Time - Arrival Time.
- Calculate Waiting Time = Turnaround Time - Burst Time.
8. Repeat Until All Complete
- Continue checking, selecting, and executing processes until all are completed.
9. Calculate Averages
- Compute average waiting time and turnaround time.
10. Output Results
- Print completion, waiting, and turnaround times for each process.
- Display the average waiting and turnaround times.
**Advantages of SRTF Scheduling
- **Minimizes Average Waiting Time: SRTF reduces the average waiting time by prioritizing processes with the shortest remaining execution time.
- **Efficient for Short Processes: Shorter processes get completed faster, improving overall system responsiveness.
- **Ideal for Time-Critical Systems: It ensures that time-sensitive processes are executed quickly.
**Disadvantages of SRTF Scheduling
- **Starvation of Long Processes: Longer processes may be delayed indefinitely if shorter processes keep arriving.
- **Difficult to Predict Burst Times: Accurate prediction of process burst times is challenging and affects scheduling decisions.
- **High Overhead: Frequent context switching can increase overhead and slow down system performance.
- **Not Suitable for Real-Time Systems: Real-time tasks may suffer delays due to frequent preemptions.
**Examples to show working of Pre-emptive Shortest Job First CPU Scheduling Algorithm
Scenario 1: Processes with Same Arrival Time
**Example: Consider the following table of arrival time and burst time for three processes **P1, P2 and P3.
**Process | **Burst Time | **Arrival Time |
---|---|---|
P1 | 6 ms | 0 ms |
P2 | 8 ms | 0 ms |
P3 | 5 ms | 0 ms |
**Step-by-Step Execution:
- **Time 0-5 (P3): P3 runs for 5 ms (total time left: 0 ms) as it has shortest remaining time left.
- **Time 5-11 (P1): P1 runs for 6 ms (total time left: 0 ms) as it has shortest remaining time left.
- **Time 11-19 (P2): P2 runs for 8 ms (total time left: 0 ms) as it has shortest remaining time left.
**Gantt chart :
Now, lets calculate average waiting time and turn around time:
As we know,
- **Turn Around time = Completion time - arrival time
- **Waiting Time = Turn around time - burst time
Process | Arrival Time(AT) | Burst Time(BT) | Completion Time (CT) | Turn Around Time (TAT) | Waiting Time (WT) |
---|---|---|---|---|---|
P1 | 0 | 6 | 11 | 11-0 = 11 | 11-6 = 5 |
P2 | 0 | 8 | 19 | 19-0 = 19 | 19-8 = 11 |
P3 | 0 | 5 | 5 | 5-0 = 5 | 5-5 = 0 |
Now,
- **Average Turn around time = (11 + 19 + 5)/3 = 11.6 ms
- **Average waiting time = (5 + 0 + 11 )/3 = 16/3 = 5.33 ms
Scenario 2: Processes with Different Arrival Times
Consider the following table of arrival time and burst time for three processes P1, P2 and P3.
**Process | **Burst Time | **Arrival Time |
---|---|---|
P1 | 6 ms | 0 ms |
P2 | 3 ms | 1 ms |
P3 | 7 ms | 2 ms |
**Step-by-Step Execution:
- **Time 0-1 (P1): P1 runs for 1 ms (total time left: 5 ms) as it has shortest remaining time left.
- **Time 1-4 (P2): P2 runs for 3 ms (total time left: 0 ms) as it has shortest remaining time left among P1 and P2.
- **Time 4-9 (P1): P1 runs for 5 ms (total time left: 0 ms) as it has shortest remaining time left among P1 and P3.
- **Time 9-16 (P3): P3 runs for 7 ms (total time left: 0 ms) as it has shortest remaining time left.
**Gantt chart :
Now, lets calculate average waiting time and turn around time:
Process | Arrival Time (AT) | Burst Time (BT) | Completion Time (CT) | Turn Around Time (TAT) | Waiting Time (WT) |
---|---|---|---|---|---|
P1 | 0 | 6 | 9 | 9-0 = 9 | 9-6 = 3 |
P2 | 1 | 3 | 4 | 4-1 = 3 | 3-3 = 0 |
P3 | 2 | 7 | 16 | 16-2 = 14 | 14-7 = 7 |
- **Average Turn around time = (9 + 14 + 3)/3 = 8.6 ms
- **Average waiting time = (3 + 0 + 7 )/3 = 10/3 = 3.33 ms
Code Implementation
Program to implement Shortest Remaining Time First is as follows:
C++ `
#include #include #include using namespace std;
struct Process { int id, arrivalTime, burstTime, remainingTime, waitingTime, turnaroundTime, completionTime; };
int main() { int n, currentTime = 0, completed = 0; cout << "Enter number of processes: "; cin >> n; vector p(n);
for (int i = 0; i < n; i++) {
p[i].id = i + 1;
cin >> p[i].arrivalTime >> p[i].burstTime;
p[i].remainingTime = p[i].burstTime;
}
while (completed < n) {
int idx = -1;
for (int i = 0; i < n; i++) {
if (p[i].arrivalTime <= currentTime && p[i].remainingTime > 0 && (idx == -1 || p[i].remainingTime < p[idx].remainingTime)) {
idx = i;
}
}
if (idx != -1) {
p[idx].remainingTime--;
currentTime++;
if (p[idx].remainingTime == 0) {
p[idx].completionTime = currentTime;
p[idx].turnaroundTime = currentTime - p[idx].arrivalTime;
p[idx].waitingTime = p[idx].turnaroundTime - p[idx].burstTime;
completed++;
}
} else {
currentTime++;
}
}
double totalWT = 0, totalTAT = 0;
for (auto &proc : p) {
totalWT += proc.waitingTime;
totalTAT += proc.turnaroundTime;
cout << "P" << proc.id << " CT: " << proc.completionTime << " WT: " << proc.waitingTime << " TAT: " << proc.turnaroundTime << endl;
}
cout << "Avg WT: " << totalWT / n << " Avg TAT: " << totalTAT / n << endl;
}
Java
import java.util.*;
class Process { int id, arrivalTime, burstTime, remainingTime, waitingTime, turnaroundTime, completionTime;
public Process(int id, int arrivalTime, int burstTime) {
this.id = id;
this.arrivalTime = arrivalTime;
this.burstTime = burstTime;
this.remainingTime = burstTime;
}
}
public class SRTF { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); Process[] processes = new Process[n];
for (int i = 0; i < n; i++) {
int arrivalTime = sc.nextInt(), burstTime = sc.nextInt();
processes[i] = new Process(i + 1, arrivalTime, burstTime);
}
Arrays.sort(processes, Comparator.comparingInt(p -> p.arrivalTime));
int currentTime = 0, completed = 0;
while (completed < n) {
int idx = -1;
for (int i = 0; i < n; i++) {
if (processes[i].arrivalTime <= currentTime && processes[i].remainingTime > 0 && (idx == -1 || processes[i].remainingTime < processes[idx].remainingTime)) {
idx = i;
}
}
if (idx != -1) {
processes[idx].remainingTime--;
currentTime++;
if (processes[idx].remainingTime == 0) {
processes[idx].completionTime = currentTime;
processes[idx].turnaroundTime = currentTime - processes[idx].arrivalTime;
processes[idx].waitingTime = processes[idx].turnaroundTime - processes[idx].burstTime;
completed++;
}
} else {
currentTime++;
}
}
double totalWT = 0, totalTAT = 0;
for (Process p : processes) {
totalWT += p.waitingTime;
totalTAT += p.turnaroundTime;
System.out.println("P" + p.id + " CT: " + p.completionTime + " WT: " + p.waitingTime + " TAT: " + p.turnaroundTime);
}
System.out.println("Avg WT: " + totalWT / n + " Avg TAT: " + totalTAT / n);
}
}
Python
class Process: def init(self, id, arrival_time, burst_time): self.id = id self.arrival_time = arrival_time self.burst_time = burst_time self.remaining_time = burst_time
def srtf(processes): current_time, completed = 0, 0 while completed < len(processes): idx = -1 for i, p in enumerate(processes): if p.arrival_time <= current_time and p.remaining_time > 0 and (idx == -1 or p.remaining_time < processes[idx].remaining_time): idx = i if idx != -1: processes[idx].remaining_time -= 1 current_time += 1 if processes[idx].remaining_time == 0: processes[idx].completion_time = current_time processes[idx].turnaround_time = current_time - processes[idx].arrival_time processes[idx].waiting_time = processes[idx].turnaround_time - processes[idx].burst_time completed += 1 else: current_time += 1
def print_results(processes): total_wt, total_tat = 0, 0 for p in processes: total_wt += p.waiting_time total_tat += p.turnaround_time print(f"P{p.id} CT: {p.completion_time} WT: {p.waiting_time} TAT: {p.turnaround_time}") print(f"Avg WT: {total_wt / len(processes)} Avg TAT: {total_tat / len(processes)}")
n = int(input("Enter number of processes: ")) processes = [Process(i + 1, *map(int, input(f"Enter arrival and burst time for P{i + 1}: ").split())) for i in range(n)] srtf(processes) print_results(processes)
`
Output
Enter number of processes: Avg WT: -nan Avg TAT: -nan