5.3.16 · D5MLOps & Deployment

Question bank — Cost optimization and inference latency

2,905 words13 min readBack to topic

Symbols used on this page (define before you use)

Everything below is invoked in the questions. Read these once so no symbol is a mystery.


Where does come from? (derived here, not assumed)

The queueing questions below all lean on one formula. Here is why it is true, so you never treat it as a magic incantation.

Step 1 — Little's Law (a counting identity). Watch the server for a long time. Every request that enters must leave, so the average number inside, , equals how fast they arrive, , times how long each stays, : This is just "stuff in = flow in × time each stays" — think of people in a shop = arrivals/min × minutes each shops.

Step 2 — where does come from? (the balance, made visual). Picture the system as a row of numbered boxes: box = "empty", box = "one request in system", box = "two", and so on. Figure 1 draws this ladder. Requests arrive at rate , so at every box you step right (up one) at rate ; the single server finishes at rate , so at every box you step left (down one) at rate .

In the long run each cut between box and box must have equal traffic crossing each way — otherwise probability would pile up on one side forever. Let be the long-run chance of being in box . Balancing the flow across the cut: So each box is times as likely as the one before it — a constant shrink factor . Chaining from box : . The chances must sum to , and for , forcing . That gives the geometric law

Step 3 — average the ladder. The average number in system is the mean of that geometric distribution: Look at the red curve in Figure 2: harmless and flat until , then it rockets up — that shape is the whole story of the "latency cliff."

Figure — Cost optimization and inference latency

Step 4 — combine (Little's Law again). Put Step 3's into Step 1 and use : What it looks like: at you get (no line, just the work); at the denominator and . That divergence is the cliff every trap below circles around.

Figure — Cost optimization and inference latency

What horizontal scaling actually does to the queue (M/M/c)

Doubling replicas is not magic — it is the M/M/c model: identical servers share one queue. The effective utilization drops to , because workers share the same arrival stream.

Why "double replicas halves queue-delay" is only roughly true: halving moves you down the nonlinear curve, so the queueing-delay reduction depends on where you started. From the wait shrinks dramatically; from it barely moves because there was almost no queue to remove. See Autoscaling and Horizontal Scaling and Little's Law and Queueing Theory.


A picture of the roofline (so "beyond the roofline" means something)

Figure — Cost optimization and inference latency

True or false — justify

Doubling the number of server replicas always halves the latency.
False. In M/M/c, extra replicas lower and so cut queueing delay, but , and are floors replicas cannot touch — and how much queue-delay you remove depends nonlinearly on your starting .
Running a GPU at higher utilization always lowers cost per inference.
Mostly true for cost but with a hidden clause: higher raises throughput so falls — until breaks the SLA, at which point you must add hardware anyway, erasing the saving.
If mean latency is well under the SLA, the SLA is safe.
False. The SLA is set on , and the mean can be tiny while the tail is huge; a page making 100 backend calls, each with a chance of hitting the slow tail, has a chance of at least one slow call — so the mean tells you little about felt quality.
Bigger batches always give more throughput.
False beyond the roofline. Once you saturate memory bandwidth (Roofline Model of Hardware Performance) throughput flattens, yet the wait-to-fill time keeps climbing — so latency rises for zero throughput gain.
Quantization to int8 is a free win because benchmarks show negligible accuracy drop.
False. Aggregate benchmarks hide the long tail; int8 can degrade badly on out-of-distribution or adversarial slices, so it is only free after you validate on those held-out slices.
An M/M/1 queue at has a finite but large mean latency.
False. has in the denominator, so the mean diverges — the queue grows without bound, it is not merely "large".
Caching lowers cost but has no effect on latency.
False. A hit skips the entire forward pass, so it slashes and cost — that is why KV-cache and response caches are two-for-one wins.
Distillation and quantization are two names for the same optimization.
False. Model Distillation trains a smaller model (fewer FLOPs ); Model Quantization and Pruning keeps the architecture but uses fewer bits per number. They reduce by different mechanisms and can be stacked.
Efficiency in can equal 1 with perfect code.
Effectively false in practice — always because of memory stalls, kernel-launch overhead and un-fused ops; even flawless code hits the memory wall, so the floor is , not .
Merging two servers into one M/M/1 with a shared queue is always worse than two separate M/M/1 queues.
False — it is the opposite. One shared queue feeding servers (M/M/c) beats isolated queues, because no server sits idle while another's private line grows; pooling smooths the load.

Spot the error

"Our dropped 30%, so users are 30% happier."
The error is optimizing the median. Half the requests are below and unaffected in feel; user pain lives at , which this statement never measured.
"We're at 98% GPU utilization — beautifully efficient, ship it."
At , : latency is 50× the service time . High utilization here means the SLA is almost certainly blown, not that the system is healthy.
"Set batch size to 512 to maximize throughput."
Missing the max-wait cap. To fill you may wait far past the SLA, and past the roofline you gain no throughput — the correct control is a timeout that flushes a partial batch.
"Cost per 1M is high, so buy a faster (pricier) GPU."
Confuses hourly price with cost-per-million . Since , a pricier machine raises ; it only helps if it raises throughput more than it raises . Often right-sizing down to cheaper hardware for a small model wins.
"Little's Law says more arrivals cause more latency, so throttle arrivals."
Misreads the law. is a conservation identity, not a causal claim; rising raises only because rises via . The fix is capacity (lower ), not blindly throttling users.
"We cut in half with a smaller model, so latency halved."
Only halved. Total ; if compute was a small slice, end-to-end latency barely moves — always ask which term dominates first.
"We added a second replica, so queueing delay must be exactly half."
The reduction is nonlinear, not a clean half. Halving moves you along the curved ; the drop is huge if you started near the cliff and negligible if you started nearly idle.
"Autoscaling failed us — latency spiked before new pods came up."
Not a design error, a lag. Scaling reacts on a delay while overshoots toward 1; the fix is headroom (scale at , not ) and predictive/pre-warmed scaling, per Autoscaling and Horizontal Scaling.

Why questions

Why measure latency at percentiles instead of reporting one average?
Because perceived quality is set by the worst requests a user actually meets, and fan-out (one page → many backend calls) makes the rare tail likely to appear at least once — with 100 calls each -risky, the chance of a slow one is .
Why does the compute floor use and not peak ?
Peak is a hardware datasheet fantasy reached only by ideal kernels; real workloads stall on memory and overhead, so the achievable rate is with efficiency — dividing work by the honest rate gives the honest floor.
Why is cost per inference inversely proportional to throughput?
The machine's hourly price is fixed whether it serves 1 or 1000 requests; spreading that fixed cost over more completed requests () is exactly why batching and higher utilization save money.
Why does batching lower cost but risk latency?
A GPU processing one request wastes most cores, so grouping requests costs slightly more compute but ~ throughput — the price is the wait to collect those requests, which adds to .
Why target rather than as high as possible?
That range keeps finite and stable while still amortizing cost well; it also leaves headroom for traffic bursts and for autoscaling lag before overshoots toward the cliff.
Why does one shared queue over servers (M/M/c) beat private queues?
Because pooling prevents the waste where one server idles while another's private line backs up; a shared queue always hands the next request to whichever worker frees first, smoothing load and shortening waits.
Why can two systems with identical hardware and model have wildly different tail latency?
Because tail latency is dominated by , which depends on utilization , batching policy, and neighbor interference — configuration and environment, not silicon, set the tail.
Why validate quantized models on adversarial and long-tail slices specifically?
Because low-bit arithmetic degrades most where the signal is subtle or out-of-distribution; aggregate accuracy averages that damage away, so only slice-level testing exposes it.

Edge cases

What happens to as (near-idle server)?
It approaches , the raw service time — with no one else in line there is no queueing, so latency is just the work itself, the best case.
What is for the very first request after a cold start?
Zero queueing, but balloons — model load, weight paging and JIT warmup dominate, which is why cold-start latency is a separate, often larger problem than steady-state.
If arrival rate exceeds service rate (), what does the formula say and what really happens?
The formula gives a negative "latency", which is nonsense — physically the queue grows unboundedly forever, so the system is unstable and you must add capacity, not tune it.
For a batch size of exactly , what is the batching benefit?
None — you pay the per-request kernel-launch overhead with nothing to amortize it over, which is precisely the wasteful single-request case batching exists to fix.
In M/M/c, what happens as you add servers while arrival rate stays fixed?
Utilization falls toward , so queueing delay vanishes and latency bottoms out at the compute floor ; beyond that point extra replicas only add idle cost, so autoscaling should stop.
At the roofline's compute-bound region, what does adding memory bandwidth buy you?
Nothing for throughput — you are limited by arithmetic, not data movement, so the fix is fewer FLOPs (distillation) or faster arithmetic (quantization), per Roofline Model of Hardware Performance.
Why can latency spike on a shared GPU even when your looks moderate?
Multi-tenant "noisy neighbors" — another tenant's job contends for memory bandwidth, cache, and SM occupancy, inflating your effective service time ; the queueing cliff then fires at a lower apparent utilization than you measured in isolation.
What SLA behavior should you expect during a traffic spike before autoscaling catches up?
A temporary overshoot pushes up sharply; a well-set SLO (SLA SLO and Monitoring) tolerates brief breaches within an error budget rather than demanding zero-violation perfection.
If a response cache has a 100% hit rate, what dominates latency?
plus a tiny lookup — compute vanishes entirely, so the network round trip becomes the irreducible floor, and no model optimization can help further.

Recall One-line summary of the traps

Almost every trap is one of three: (1) confusing mean with tail, (2) forgetting the cliff near full utilization, or (3) treating a single lever's local win as an end-to-end win when another latency term dominates.