Queue depth buys overlap until a bottleneck buys waiting
Relate application concurrency, block queues, service latency, and throughput while distinguishing device parallelism from time spent waiting.
On this page
The question for today
What you’ll understand
- Distinguish queue depth at the application, software, and device boundaries.
- Apply Little's law with consistent completion and latency definitions.
- Design a queue-depth sweep that exposes saturation and latency costs rather than maximizing one benchmark number.
One request at a time may leave a parallel device idle, while thousands of outstanding requests may produce little extra throughput and long waits. Queue depth is the amount of concurrent unfinished work at a chosen boundary. Its useful value depends on request size, device parallelism, completion latency, and competing traffic. The engineering task is to identify enough overlap for the workload without confusing a growing backlog with growing capacity.
Name the queue whose depth you measured
A task can wait in application code, an asynchronous runtime, a filesystem path, software block queues, a hardware submission queue, or the device's internal machinery. Those are not interchangeable counters. Linux's multi-queue block layer organizes software submission and hardware-dispatch queues to support scalable I/O, while scheduling and request merging can change what reaches a device. Application operations can split into several block requests or combine with neighboring work. Report the boundary, request definition, and time interval before comparing queue depth across tools.
Scheduling policies trade throughput, fairness, latency, and overhead for particular devices and workloads. A policy useful for reducing mechanical seeks need not be best for an SSD or a mixed workload. Multiple hardware queues can reduce host lock contention but do not make every request independent: shared bandwidth, firmware, flash channels, and synchronization requirements still constrain service. A durability-sensitive flush can also impose dependencies that ordinary independent read benchmarks avoid. Inspect the configured scheduler and actual device characteristics rather than prescribing one universally optimal queue shape.
Overlap hides latency only until resources saturate
For a simplified set of independent requests, enough outstanding work lets the device overlap operations rather than wait for each round trip. Once a shared resource is saturated, additional depth mostly increases waiting. If throughput stops growing while residence time and unfinished work rise, the useful conclusion is not that capacity increased. For an interactive service, tail latency may worsen before average throughput reaches its maximum. Set a latency target and consider competing tenants rather than choosing depth solely from the largest IOPS value.
Request size creates another ceiling. A device capable of many small operations can still hit a byte-per-second bottleneck for large transfers, and a nominal bandwidth figure does not predict small synchronized-write latency. Keep units explicit: requests per second multiplied by bytes per request gives bytes per second only for the stated request population. CPU submission overhead, checksumming, copying, and filesystem work may become bottlenecks before hardware. Compare application and device utilization carefully; an underfed device with a saturated application thread calls for a different change than an overloaded device queue.
Sweep depth and preserve the workload contract
Run several depths while holding request size, read/write mix, address distribution, cache policy, synchronization semantics, dataset, and steady-state preparation fixed. Record achieved depth rather than only configured depth, and report completion errors as failures rather than fast successful requests. Track throughput, median and high-percentile latency, CPU use, and relevant queue counters. An asynchronous API can submit rapidly while completion lags far behind; measure completion at the boundary the user cares about. A sweep that silently disables synchronization at higher depths compares different contracts.
The queue lab provides a simpler contrast, with fluid backlog starting at four and no hardware-depth control or parallel flash channels. Press Reset, set both arrival to one and service to three, predict the stable M/M/1 mean residence of half a second, then Play or Step. For a separate smaller-margin comparison, Reset, set both arrival to two and service to three, predict one second, then Play or Step. Edits retain elapsed time and recalculate fluid backlog from the initial four, so they are not live rate changes. The separate residence formula assumes Poisson arrivals and exponential single-server service; it is not a measured SSD latency curve.
Work it through
Interpret two queue-depth measurements
At one consistent application boundary, a stable workload completes 40,000 requests/s with mean residence 0.4 ms. A higher-depth run completes 42,000 requests/s with mean residence 1.2 ms. Each request is 4,096 bytes.
Convert milliseconds to seconds and apply Little's law: the first run averages 40,000 × 0.0004 = 16 unfinished requests.
The second run averages 42,000 × 0.0012 = 50.4 unfinished requests. Throughput rises only five percent while mean residence triples and outstanding work rises by more than threefold.
Payload throughput is 163,840,000 bytes/s in the first run and 172,032,000 bytes/s in the second. Decide whether that additional 8,192,000 bytes/s justifies the latency cost under the service's target.
More unfinished work provided a small throughput gain at a large waiting cost. The measurements support a tradeoff decision, not a universal optimal depth or a claim about tail latency.
The living notebook
Explore the model
Interactive lab · queue
Service margin and unfinished work
Reset, set both λ=1 and μ=3, predict the separate stable M/M/1 residence estimate, then Play or Step. Reset, re-enter both λ=2 and μ=3, predict the narrower-margin estimate, then Play or Step. Each Reset starts a fresh fluid run at four; slider edits retain elapsed time. There is no hardware-depth control, parallel device model, or SSD latency predictor.
- Fluid backlog
- 4
- Net rate · λ − μ
- −1 /s
- M/M/1 mean residence
- 1 s
Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forMore concurrent unfinished requests can increase waiting after a bottleneck saturates; measure the actual boundary and latency target.
Pause & reason
Check your understanding
Your turn
Try it yourself
A stable storage boundary completes 25,000 requests/s with a mean residence of 2 ms. Estimate average unfinished requests. If throughput stays fixed while mean residence halves, what happens to that average?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Convert milliseconds to seconds and use the same boundary in both measurements.
Compare with the solution
Average unfinished work is 25,000 × 0.002 = 50 requests. At one millisecond and unchanged throughput it becomes 25 requests. This says nothing directly about the configured application queue limit, individual hardware queue counts, or high-percentile latency; those are separate observations.
Keep the idea
Take it with you
- Queue depth is meaningful only with a named request population and boundary.
- Little's law connects completed throughput, residence time, and average unfinished work.
- Choose concurrency from measured throughput-latency tradeoffs while preserving synchronization semantics.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.