Elevator algorithm
The elevator algorithm, also known as the SCAN algorithm, is a disk scheduling technique in operating systems that optimizes the movement of the disk read/write head by servicing pending requests in a unidirectional sweep across the disk surface, reversing direction only upon reaching an endpoint, much like an elevator traversing floors in a building.[1][2]
In operation, the algorithm maintains a queue of disk requests sorted by track number; the head starts from its current position and moves inward or outward—depending on the initial direction—servicing all requests it passes until it hits the disk's boundary (track 0 or maximum), at which point it reverses and services the remaining requests in the opposite direction.[2][3] This process repeats for subsequent requests, ensuring that every request is eventually addressed without indefinite postponement, thus avoiding starvation.[1][4]
The algorithm excels in high-load scenarios by minimizing total head movement—often outperforming first-come, first-served (FCFS) and shortest-seek-time-first (SSTF) methods, as demonstrated in examples where it reduces seek distances from 640 cylinders (FCFS) to around 208-236 cylinders.[2][4] It balances throughput and fairness better than purely greedy approaches like SSTF, which can lead to starvation of distant requests, while providing lower response time variance than FCFS under heavy traffic.[1][3] However, it may result in longer waits for requests near recently serviced areas, prompting variants like C-SCAN (circular SCAN), which returns the head to the starting point without servicing on the reverse trip for more uniform latency, or LOOK, which halts at the farthest request rather than the disk end to shave unnecessary travel.[2][3]
As a modular component of the operating system kernel, the elevator algorithm can be swapped or tuned independently, making it adaptable to different hardware and workloads; however, in modern SSDs, where traditional seek-based optimizations are less relevant due to the absence of moving parts, other algorithms such as deadline-based scheduling (incorporating request deadlines) are used to enhance latency guarantees.[5][6]
Introduction
Definition
The elevator algorithm, also known as the SCAN algorithm, is a disk scheduling technique used in operating systems to optimize the movement of the disk read/write head. It services pending read and write requests by moving the head in a unidirectional sweep across the disk tracks, servicing all requests in one direction before reversing at the disk's endpoint, similar to how an elevator services floors in a building.[7]
Key concepts include the queue of disk requests sorted by track number, the current position of the disk head, and its direction of travel (inward or outward). For example, if moving toward higher track numbers, the head services all requests with tracks greater than or equal to its current position until reaching the maximum track, then reverses to service the remaining requests.[8][1]
This approach is named for its analogy to elevator dispatching, where the "elevator" (disk head) continues in one direction, fulfilling requests encountered before changing course, promoting efficient resource allocation in both mechanical and computational systems.[9]
In contrast to the first-come, first-served (FCFS) algorithm, which processes requests in arrival order and can result in excessive head movement due to erratic jumps, the elevator algorithm groups requests by direction to reduce total seek time and promote more predictable disk access patterns.[10][8]
Purpose and Benefits
The elevator algorithm aims to minimize the total head movement and average seek time in disk I/O operations by systematically servicing requests in the current direction before reversing, thereby improving overall system performance under load.[7][1]
A primary benefit is enhanced efficiency in high-traffic scenarios, where it reduces unnecessary back-and-forth movements compared to greedy methods like shortest-seek-time-first (SSTF), which may starve distant requests. This leads to better throughput and fairness, ensuring no request is indefinitely postponed (avoiding starvation).[8][11]
Additionally, it provides lower variance in response times than FCFS, making it suitable for environments with varying workloads, and its simplicity allows easy implementation in operating system kernels. In modern contexts, while less critical for solid-state drives (SSDs) due to lack of mechanical seeks, the algorithm's principles influence deadline-aware scheduling extensions for latency-sensitive applications.[9][8]
Historical Development
Origins
The elevator algorithm, or SCAN, for disk scheduling originated in the early 1970s as part of efforts to optimize input/output operations on early hard disk drives, where seek times dominated performance. It was formalized and analyzed in academic literature amid the growth of minicomputers and mainframes, such as the IBM System/360, which used rotating disk storage requiring efficient request ordering to minimize head movement.[12]
A foundational analysis appeared in 1972 with the paper "Analysis of Scanning Policies for Reducing Disk Seek Times" by E. G. Coffman Jr., L. A. Klimko, and B. Ryan, published in the SIAM Journal on Computing. The authors modeled head motion under scanning policies, demonstrating that unidirectional sweeps (SCAN) balanced seek time reduction with fairness, outperforming earlier methods like first-come, first-served (FCFS). Concurrently, T. J. Teorey and J. P. Pinkerton's "A Comparative Analysis of Disk Scheduling Policies" in Communications of the ACM compared SCAN with shortest-seek-time-first (SSTF) and others, highlighting its advantages in high-load scenarios through simulation.[13] These works established SCAN as a standard technique, inspired by elevator dispatching but adapted for linear track layouts on disks.
Evolution and Adoption
By the late 1970s and 1980s, the algorithm was integrated into commercial operating systems as disk capacities and speeds increased. Early UNIX variants, such as Version 7 (1979), employed basic disk scheduling, with SCAN-like policies emerging in research and proprietary systems to handle growing I/O demands in multitasking environments.[14]
The term "elevator" gained prominence in the Linux kernel, where I/O schedulers were abstracted as an "elevator" layer. The initial implementation, known as the "Linus Elevator," appeared in Linux 2.4 (released January 2001), using a deadline-based variant of SCAN to merge and reorder requests for fairness and throughput.[15] In Linux 2.6 (2003), this evolved into multiple options, including the Complete Fair Queuing (CFQ) scheduler, which incorporated elevator principles with per-process queues to prevent starvation.[16]
Adoption extended to other systems, such as Windows NT kernels using similar rotational policies, and BSD variants. By the 2010s, with the rise of solid-state drives (SSDs), traditional seek-optimized algorithms like SCAN became less critical due to negligible access latencies, prompting shifts to deadline and multi-queue schedulers (e.g., Linux's mq-deadline in 2018 and BFQ for fairness). As of 2025, the elevator framework persists in Linux for hybrid storage, influencing NVMe optimizations and real-time systems.[17]
Core Mechanics
Basic Operation
The elevator algorithm, also known as the SCAN algorithm, operates by simulating the motion of an elevator in a building, where the disk head serves as the elevator and disk tracks represent floors. In a single-head scenario, the algorithm initializes the disk head at a specific track position, often determined by the current location when requests arrive, and assigns an initial direction—typically upward (toward higher track numbers) or downward (toward lower track numbers)—based on the distribution of pending requests. This setup ensures that the head begins servicing from its starting point without unnecessary backtracking.[18][1]
During the scanning phase, the head moves continuously in its current direction, stopping to service all requests encountered along the way in sorted order within that direction. It only pauses for requests that align with the travel path—for instance, if moving upward from track 50, it services any pending requests at tracks 60, 70, and 90 before proceeding further—until it reaches the end of the disk (track 0 or the maximum track, such as 199). This unidirectional sweep to the boundary minimizes seek time by grouping services efficiently while avoiding reversals mid-scan. New requests arriving during the scan are queued for the next pass in the appropriate direction to maintain fairness.[19][20]
Upon completing the scan by hitting a disk boundary, the algorithm triggers a reversal: the head changes direction and begins servicing the opposite set of queued requests on the return trip. For example, after scanning upward to the maximum track, it reverses downward, now stopping for previously unserved requests below the reversal point. This process repeats, alternating directions, until all requests are fulfilled, at which point the head idles or resets to a default position awaiting new inputs. The reversal logic relies on simple conditional checks following the boundary reach: the head then services requests in the new direction until the opposite boundary.[18][1]
The core decision-making can be outlined in pseudocode as follows, focusing on direction changes based on pending calls and boundary reaches:
Initialize: current_position = initial_track; direction = UP (or DOWN based on requests);
Queue requests sorted by track number;
disk_min = 0; disk_max = 199; // Example disk boundaries
While requests remain:
If direction == UP:
// Service requests > current_position
While there are requests > current_position:
Move to next request > current_position;
Service request;
Update current_position;
// Move to disk end if not already there
If current_position < disk_max:
Move to disk_max;
current_position = disk_max;
// Reverse if requests remain in opposite direction
If there are requests < current_position:
direction = DOWN;
Else:
// All done or wait for new
break;
Else (direction == DOWN):
// Service requests < current_position
While there are requests < current_position:
Move to next request < current_position;
Service request;
Update current_position;
// Move to disk end if not already there
If current_position > disk_min:
Move to disk_min;
current_position = disk_min;
// Reverse if requests remain in opposite direction
If there are requests > current_position:
direction = UP;
Else:
// All done or wait for new
break;
Initialize: current_position = initial_track; direction = UP (or DOWN based on requests);
Queue requests sorted by track number;
disk_min = 0; disk_max = 199; // Example disk boundaries
While requests remain:
If direction == UP:
// Service requests > current_position
While there are requests > current_position:
Move to next request > current_position;
Service request;
Update current_position;
// Move to disk end if not already there
If current_position < disk_max:
Move to disk_max;
current_position = disk_max;
// Reverse if requests remain in opposite direction
If there are requests < current_position:
direction = DOWN;
Else:
// All done or wait for new
break;
Else (direction == DOWN):
// Service requests < current_position
While there are requests < current_position:
Move to next request < current_position;
Service request;
Update current_position;
// Move to disk end if not already there
If current_position > disk_min:
Move to disk_min;
current_position = disk_min;
// Reverse if requests remain in opposite direction
If there are requests > current_position:
direction = UP;
Else:
// All done or wait for new
break;
This structure ensures systematic coverage without starvation, as every request will eventually align with a scan direction.[7][19]
Request Processing
In the elevator algorithm, disk I/O requests—specifying read or write operations to particular tracks—are collected in a central queue maintained by the operating system kernel. The queue is typically kept sorted by track number to facilitate efficient traversal during scans, allowing quick identification of requests in the current direction.[7]
New requests arrive asynchronously from processes and are added to the queue in real-time, inserted at the appropriate position based on track number without interrupting the ongoing scan; for example, a request for track 80 during an upward sweep from track 50 would be queued for servicing if 80 > 50, or deferred to the return trip otherwise. This dynamic insertion ensures fairness, as requests are not discarded but prioritized by the algorithm's directional logic rather than arrival order.[4]
Integration occurs seamlessly during each sweep: as the head moves, the controller scans the queue for the next eligible request matching the direction (e.g., tracks greater than current for upward), servicing them in ascending/descending order while ignoring opposite-direction ones until reversal. The direction indicator—a simple flag (up or down)—filters the queue access, ensuring the head responds only to compatible requests until a boundary is reached.[1]
Edge cases, such as an empty queue in the current direction, are handled by proceeding directly to the disk boundary before reversal, preventing unnecessary idling. High-priority or deadline-sensitive requests (in extended variants) may be flagged in the queue for potential overrides, though standard SCAN treats all equally to avoid complexity. Overloaded queues under heavy I/O load are managed by the OS scheduler, which may throttle new requests temporarily to maintain system stability.[2][7]
Variations
Standard Modifications
The LOOK variant improves upon the basic elevator algorithm by reversing the disk head's direction only upon reaching the farthest pending request in the current direction, rather than proceeding to the disk's endpoint (track 0 or maximum). This modification eliminates unnecessary empty travel beyond active requests, thereby reducing seek time compared to the standard SCAN approach.[21][2]
The C-SCAN variant adopts a unidirectional scanning pattern, where the disk head services requests in one direction from the innermost to outermost track (or vice versa), then jumps back to the starting track without servicing requests on the return path. This treats the disk tracks as a circular queue, ensuring more uniform waiting times for requests across the disk surface.[21][3]
The C-LOOK variant combines elements of C-SCAN and LOOK, servicing requests in one direction up to the farthest request, then jumping to the farthest request in the opposite direction without full traversal to the disk end. This further optimizes seek distances by avoiding empty sweeps, making it particularly efficient for workloads with clustered requests.[2]
Early studies on these seek-reducing modifications, including LOOK and C-SCAN variants, reported performance improvements such as 5-10% lower average response times under medium to heavy loads compared to less adaptive methods, with up to 40% reductions in specific traced workloads.[21]
Modern Enhancements
In modern storage systems, particularly solid-state drives (SSDs), traditional seek-based algorithms like SCAN have diminished relevance due to the absence of mechanical heads and uniform access latencies. Instead, enhancements focus on deadline-based scheduling, where requests are prioritized by assigned deadlines to guarantee latency bounds, or the Noop scheduler, which simply merges and reorders requests without complex scanning to leverage SSD parallelism.[6]
Multi-queue schedulers, such as mq-deadline or BFQ in Linux kernels (as of 2025), extend SCAN principles to handle concurrent I/O streams from NVMe SSDs by distributing requests across queues and applying variants like deadline enforcement per queue, improving throughput by 20-50% in multi-threaded workloads compared to single-queue SCAN.[6] These adaptations incorporate request aging to prevent starvation, similar to SCAN's fairness, while optimizing for flash-specific constraints like write amplification.
Examples
Simple Illustration
Consider a disk with 200 tracks where the read/write head starts at track 50, moving toward track 0 (inward). Suppose pending read/write requests are at tracks 176, 79, 34, 60, 92, 11, 41, and 114.[7]
In this setup, the elevator algorithm (SCAN) services all requests in the current direction before reversing. Starting inward, the head moves to track 41, then 34, then 11. It continues to the disk's inner boundary at track 0 (even without a request there), servicing no additional requests en route. Upon reaching track 0, it reverses direction and moves outward, servicing the remaining requests at 60, 79, 92, 114, and finally 176. With no further requests, the process ends.
The execution can be visualized as a seek sequence: 50 → 41 → 34 → 11 → 0 → 60 → 79 → 92 → 114 → 176, illustrating the scan-like motion across tracks without unnecessary reversals mid-sweep.[8]
This illustration results in nine seeks and a total head movement of 226 tracks (calculated as |50-41| + |41-34| + |34-11| + |11-0| + |0-60| + |60-79| + |79-92| + |92-114| + |114-176|), demonstrating efficient servicing in a basic single-disk scenario compared to alternatives like FCFS, which might exceed 300 tracks for the same requests.[7]
Multi-Elevator Scenario
In multi-disk systems, the elevator algorithm can operate across multiple drives managed by a storage controller, where requests are assigned to individual disks to optimize overall I/O performance. A representative setup involves a RAID array or server with 3 disks, each handling up to thousands of IOPS depending on the model. The assignment prioritizes the disk closest to the data location, matching request type (read/write) and current load capacity to avoid bottlenecks and ensure balanced distribution.[21]
To illustrate coordination, consider a scenario where requests arrive dynamically. Disk A, with head at track 30 and scanning inward, receives assignments for requests at tracks 50 and 70; it serves these sequentially without reversing prematurely, adhering to the SCAN principle of completing directional sweeps. Concurrently, Disk B, scanning outward from track 150, handles requests at tracks 140 and 120, minimizing seek times for aligned directions. If Disk B nears capacity limits—say, exceeding 80% utilization—the controller dynamically reassigns queued requests to Disk C, which may be idle or better positioned, preventing I/O stalls.[21]
The storage controller applies elevator algorithm logic per disk by evaluating factors like estimated seek time and directional alignment to minimize conflicts where disks handle unbalanced workloads inefficiently. This includes rules to balance load during peak traffic and to zone assignments for high-demand data areas, ensuring no single disk handles disproportionate requests.[21]
Such coordinated operation yields improvements in system efficiency, including reduced average response times and better throughput distribution; for instance, variants like C-LOOK in zoned multi-disk setups have shown over 20% better response times than non-scheduled approaches in simulated environments with prefetching caches.[21]
Analysis
The performance of the elevator algorithm (SCAN) in disk scheduling is evaluated using key metrics that quantify efficiency in servicing I/O requests. These include total head movement, which measures the cumulative distance the disk head travels to service requests; average seek time, representing the typical time for head positioning; throughput, indicating requests processed per unit time; and variance in response times, reflecting fairness in servicing. Power consumption, tied to seek operations, is also considered in energy-aware systems.[22][2]
Total head movement is the sum of absolute differences in track positions as the head services requests in directional order:
\text{Total Head Movement} = \sum |p_{i} - p_{i+1}|
where p_i are the track positions serviced. In an example with requests at tracks 98, 183, 37, 122, 14, 124, 65, 67 and head starting at 53 moving inward, SCAN achieves 208 cylinders of movement, compared to 640 for FCFS.[2]
Average seek time is the total head movement divided by the number of requests, providing an indicator of access latency. Seek time is particularly sensitive to traffic patterns, with SCAN performing well during high loads by minimizing unnecessary back-and-forth movements.[22]
Throughput measures the number of requests serviced per second, often improved by SCAN's systematic approach, which reduces overhead at the disk controller. This metric highlights the algorithm's ability to handle directional request clusters efficiently.[22]
The number of direction reversals per cycle serves as a proxy for efficiency, as excessive reversals increase latency and wear; SCAN limits reversals to endpoints, resulting in fewer interruptions than non-directional methods like SSTF. Power consumption is calculated based on seek distance and head speed, with SCAN reducing idle traversals and thus lowering usage in simulated workloads.[2]
Response time variance is low under moderate traffic due to the algorithm's fair servicing of requests in order.[22]
These metrics are typically assessed through simulation-based methods, such as trace-driven simulations using disk request logs from real workloads or synthetic patterns, or via benchmarking tools that record seek distances and latencies.[2]
Advantages and Limitations
The elevator algorithm offers predictable service by systematically scanning the disk in one direction before reversing, which minimizes variance in response times and ensures fairness by preventing indefinite starvation of requests.[23] This approach provides low computational overhead, as it relies on simple queue operations to maintain and process requests in directional order without complex optimizations.[24] It performs effectively under uniform traffic conditions, where requests are distributed evenly across the disk surface, achieving high throughput and reasonable average waiting times compared to uncoordinated methods.[25]
Despite these strengths, the algorithm struggles in zoned or bursty traffic patterns, such as clustered requests in specific disk regions, leading to prolonged waits for opposite-direction calls as the head completes full sweeps.[23] This can cause uneven load distribution, with outer zones potentially underserved during directional passes that prioritize inner areas.[26] In low-traffic scenarios, modern analyses highlight its energy inefficiency, as the head incurs unnecessary seek power for traversing empty portions of the disk, exacerbating consumption in power-sensitive environments like mobile storage.[27]
Relative to first-come-first-served (FCFS), the elevator algorithm excels under high loads by reducing overall seek distances, but it underperforms predictive variants like shortest seek time first (SSTF) during bursty peaks, where localized requests benefit more from greedy selection.[23]