ยง7.5โ€“7.10Shortest Time-to-Completion First โ€ฆ Summary

Part I OSTEP pp. 69โ€“74 ยท ~7 min read

  • stcf
  • response time
  • round robin
  • time slice
  • amortization

SJF left us hanging: B and C arrive just after A starts, and politely wait 90 seconds anyway. The fix needs the machinery from chapter 6 โ€” the timer interrupt and context switch โ€” plus the will to use it.

7.5 Shortest Time-to-Completion First (STCF)

Relax assumption 3 (run to completion). When a new job enters the system, the STCF scheduler (a.k.a. Preemptive Shortest Job First) determines which of the remaining jobs โ€” new job included โ€” has the least time left, and runs that one:

Figure 7.5: STCF โ€” preemption fixes the late-arrival convoy
AarrrunBarrrunCarrrun
CPUA: 0โ€“10AB: 10โ€“20BC: 20โ€“30CA: 30โ€“120A020406080100120
jobarrivalruntimeturnaroundresponse
A01001200
B1010100
C10102010
average50.003.33

When B and C arrive at t=10, STCF compares time-remaining (A: 90, B: 10, C: 10) and preempts A. Average turnaround: (120 + 10 + 20)/3 = 50 โ€” flip back to SJF to see 103.33 again.

Average turnaround: 50 seconds, down from SJFโ€™s 103.33. And as before, under the current assumptions, STCF is provably optimal โ€” if SJF is optimal when everyone arrives together, preempting for shorter arrivals is the natural extension.

7.6 A New Metric: Response Time

If jobsโ€™ lengths were known and the CPU were all that mattered, STCF would be the answer โ€” and for early batch systems, it nearly was. Then came time sharing: users at terminals, demanding interactivity. A new metric was born โ€” response time , the time from arrival to first being scheduled:

Tresponse=Tfirstrunโˆ’TarrivalT_{response} = T_{firstrun} - T_{arrival}

(The bookโ€™s definition is the best case โ€” it assumes the job produces a response the instant it starts.) For Figure 7.5โ€™s schedule: A responds at 0, B at 0, C at 10 โ€” average 3.33. Not bad. But make three jobs arrive together and STCF-family schedulers turn ugly: the third job waits for the entirety of the first two. Imagine typing at a terminal and waiting 10 seconds for a keystroke to echo because someone else got scheduled first.

7.7 Round Robin

Enter Round-Robin (RR): run a job for a time slice (the scheduling quantum โ€” a multiple of the timer-interrupt period), then switch to the next job in the run queue, cycling until all are done. โ€œTime-slicing.โ€ Fight it out:

Figures 7.6 & 7.7: the response-time duel โ€” SJF vs Round Robin on three 5-second jobs
AarrrunBarrrunCarrrun
CPUA: 0โ€“5AB: 5โ€“10BC: 10โ€“15C010
jobarrivalruntimeturnaroundresponse
A0550
B05105
C051510
average10.005.00

SJF: response times 0, 5, 10 (avg 5) โ€” C stares at a frozen terminal for 10 seconds. Switch to RR (quantum 1): responses 0, 1, 2 (avg 1) โ€” but turnaround jumps from 10 to 14. Now raise the quantum and watch response degrade back toward SJF.

The numbers tell the whole story of this chapter:

  • Response: RR (quantum 1) averages 1; SJF averages 5. RR wins interactivity, hands down.
  • Turnaround: RR averages 14; SJF averages 10. RR is, in the bookโ€™s phrase, nearly pessimal โ€” often worse than plain FIFO โ€” because it deliberately stretches every job as long as possible, finishing nothing early. Turnaround only cares about finishing.

Thatโ€™s an inherent trade-off, not an engineering failure: any fair policy that divides the CPU evenly on small timescales must do poorly on turnaround; be unfair (run short jobs to completion) and response time pays instead. You canโ€™t have your cake and eat it too.

Tip: Amortization can reduce costs

The quantum length is RRโ€™s critical knob. Shorter = more responsive โ€” but each switch costs. With a 1ย ms context-switch cost and a 10ย ms slice, ~10% of all time is switching overhead; stretch the slice to 100ย ms and overhead falls under 1%. That is amortization : incur the fixed cost less often. Pick a slice long enough to amortize switching, short enough to stay responsive. (And the true switch cost isnโ€™t just registers: programs build up state in CPU caches, TLBs, and branch predictors โ€” all flushed and refilled on a switch.)

7.8 Incorporating I/O

Relax assumption 4 โ€” all real programs do I/O (a program with no input always produces the same output; one with no output is the tree falling in the forest). When a running job issues an I/O it becomes blocked (chapter 4โ€™s third state), so the scheduler should run someone else; and when the I/O completes, an interrupt raises another decision.

Example: A and B each need 50 ms of CPU, but A issues a disk I/O (10 ms) after every 10 ms of computing, while B just computes. Treating A as one 50-ms lump wastes the machine:

CPUDiskAAAAAB (all 50 ms, starting at t=90)the CPU sits idle in every gap while A waits on the disk โ€” B could have used itFigure 7.8: Poor use of resources โ€” everything done at t = 140

Figure 7.8: no overlap. Aโ€™s five bursts each strand the CPU for 10 ms; B waits for all of it.

The common approach: treat each 10-ms CPU burst as an independent sub-job. Then STCFโ€™s choice is natural โ€” a 10-ms burst of A beats 50-ms B; when A blocks, B runs; when Aโ€™s I/O completes, its next burst preempts B again:

Figure 7.9: overlap allows better use of resources (STCF treating each CPU burst as a sub-job)
CPUA: 0โ€“10AB: 10โ€“20BA: 20โ€“30AB: 30โ€“40BA: 40โ€“50AB: 50โ€“60BA: 60โ€“70AB: 70โ€“80BA: 80โ€“90AB: 90โ€“100BDiskA I/O: 9โ€“20A I/O: 29โ€“40A I/O: 49โ€“60A I/O: 69โ€“80020406080100
jobarrivalruntimeturnaroundresponse
A050900
B05010010
average95.005.00

A's 10ms bursts always beat B's big remaining chunk, so A runs, blocks on the disk, and B fills the gap โ€” every gap. Everything finishes by t=100 instead of 140, because CPU and disk work concurrently.

Overlap is the win: the CPU computes for one process while the disk serves another (a tip the book generalizes: overlap operations whenever possible โ€” disk I/O, remote messages โ€” and utilization rises). Treating bursts as jobs also means โ€œinteractiveโ€ processes run frequently, while CPU-hungry ones soak up the leftovers.

7.9 No More Oracle

One assumption stands: that the scheduler knows each jobโ€™s length โ€” the worst assumption of all. In a general-purpose OS the kernel knows almost nothing about the future. So: how to build a scheduler that behaves like SJF/STCF without a priori knowledge, and folds in RRโ€™s response-time goodness?

7.10 Summary

Two scheduler families: run-the-shortest-remaining (SJF/STCF โ€” optimal turnaround, terrible response) and alternate-everyone (RR โ€” great response, nearly-pessimal turnaround); each is bad exactly where the other is good, plus a workable way to fold in I/O. The missing piece โ€” seeing the future โ€” turns out to have a beautiful answer: use the recent past to predict it. That scheduler, the multi-level feedback queue, is the next chapter.

Homework: scheduler.py

This chapterโ€™s simulator runs FIFO, SJF, and RR over job lists and reports response, turnaround, and wait times โ€” the same experiments as this pageโ€™s widgets, plus questions worth doing by hand first: when does SJF tie FIFO on turnaround? When does SJF tie RR on response? Whatโ€™s RRโ€™s worst-case response time for N jobs and quantum q? Get it at ostep-homework.

Check yourself

1.B (10s) arrives at t=10 while A (90s remaining) is running. What does STCF do that SJF cannot?

2.Three 5-second jobs arrive together. Under SJF, what is C's response time โ€” and why did time-sharing systems care?

3.With a 1 ms context-switch cost, why not set RR's quantum to 1 ms for the best possible response time?

4.Why is RR called 'nearly pessimal' for turnaround โ€” often worse than plain FIFO?

5.In Figure 7.9, A (10 ms bursts + 10 ms I/Os) and B (50 ms pure CPU) both finish by t=100 instead of 140. What made the difference?

5 questions