skip to content

Should a latency-critical component rely on the compiler proving its temporaries non-escaping, or be designed so those temporaries never exist?

level: principalimportance: should knowfreq 33%

answer

  1. an optimization, not a contract
  2. invisible in the source, invisible in review
  3. split the codebase, do not rule it out everywhere
  4. shape the interface so nothing is built
  5. hold the line with a measured number

basics

~20 s

Split the codebase. On paths with a hard latency budget, shape the interfaces so the temporary is never constructed, because the proof is an optimization with no source marker and an ordinary edit can withdraw it. Everywhere else, rely on it.

solid answer

~50 s

A non-escape proof is an **optimization, not a contract**. Nothing in the source says a value is frame-local, no type system records it, and the proof is re-established from scratch whenever the surrounding code changes — so a log line that hands the value to a formatter, a new field store, or an extension point added for another team can withdraw it silently. That argues for a split rather than a blanket rule. On the few paths with a hard tail-latency budget, design so the temporary is never created: pass the components, write into a caller-owned buffer, keep the composite inside the scope that built it. Everywhere else, depend on the proof, because the alternative costs readability on code whose allocation volume nobody will ever notice. Then hold the line with a measured per-operation allocation figure, not with a comment.

go deeper

for a junior

Know that frame-local placement is something a compiler may do, not something the program is promised, so code cannot simply assume it.

for a middle

Explain what withdraws the proof - a store, a return, a capture, an unexamined call - and why none of those is visible as such in a diff.

for a senior

Argue for a specific line: which paths must not construct a temporary at all, which may rely on the optimization, and what measurement makes a regression visible the day it lands.

for a principal

Own the trade across the codebase, including the readability the discipline costs, and make the policy structural through interface shape rather than through instructions to maintainers.

## Why this is a judgment call and not a rule Both extremes are defensible and both are wrong as a policy. Relying on the proof everywhere means the system's latency depends on an invisible property that any maintainer can remove by accident. Avoiding temporaries everywhere means writing awkward, parameter-heavy code across a whole codebase to protect paths where allocation volume would never have mattered. The decision worth defending is **where the line sits**, and on what evidence it is held. ## What makes the proof fragile - **It has no source-level marker.** Nothing declares a value frame-local, so a reviewer cannot see the property being removed in a diff. - **It is re-derived per site, from whatever is visible there.** Add an unexamined call and the evidence disappears, even if the callee would never have retained anything. - **Ordinary maintenance withdraws it.** A diagnostic that passes the value to a formatter, a new field that stores it, an extension point that hands it to a plug-in, a hand-off to another thread. - **How far the reward is taken differs between ecosystems.** Some platforms place whole values in a frame, some only dissolve them into registers, some do neither in the situation you are looking at. A design that must hold everywhere cannot assume the strongest of those. None of that makes the proof useless. It makes it a **dependency**, and dependencies are managed rather than trusted. ## Where to draw the line | path | policy | why | |---|---|---| | hard tail-latency budget, high call rate | do not create the temporary | the budget is a promise; an invisible property must not be able to break it | | ordinary service code | rely on the proof | the volume is irrelevant and the readability cost is real | | library code used by callers you do not control | do not create it on the hot entry points | you cannot see the call sites that will decide the verdict | ## How to remove a temporary without hurting the code 1. **Pass the components.** Two numbers instead of one composite is the cheapest change and removes the question entirely. 2. **Let the caller own the storage.** Fill a structure the caller already holds and hand the result back through it, so no new value is created per operation. 3. **Keep the composite inside the scope that built it.** Construct it, consume it, never let it cross a boundary the compiler cannot see through. 4. **Batch.** Operate on a run of inputs per call so any unavoidable construction is paid once rather than per element. Each of these costs expressiveness. That is the real price of not depending on the proof, and it is why this is not a codebase-wide rule. ## Holding the line A policy that lives in a comment does not survive. What survives is a number: **allocation per operation** for the paths that carry a budget, recorded and checked in the same place as latency. That turns a fragile invisible property into a visible one — not by making the proof reliable, but by making its withdrawal detectable the same day it happens. The complement is interface shape: if the hot entry point never accepts or returns a composite, no future maintainer can construct one there by accident. ## What the wrong answers look like - **'Never allocate anywhere.'** A cost imposed on the entire codebase to protect a small part of it, usually justified by an anecdote rather than a measurement. - **'The compiler handles it.'** True until the day it is not, and the day it is not looks exactly like an unrelated deploy. - **'Add a comment telling people not to change this loop.'** Comments do not survive refactors and do not constrain callers at all. - **'Make the values smaller.'** Size is not the test; reachability is. The defensible position is narrow and stated out loud: these paths carry a budget and do not construct temporaries, the rest of the system relies on the optimization like everyone else, and the per-operation figure on the budgeted paths is measured so that the assumption cannot quietly stop being true.

  • What kind of routine edit is most likely to withdraw the proof unnoticed?
    Adding a diagnostic or a metric that hands the value to a target the compiler cannot examine. The diff reads as a one-line observability improvement, the computation is unchanged, and the only effect is that a previously provable property is gone. Extension points added for other teams have the same shape.
  • How do you make the dependency visible without making the code awkward everywhere?
    Confine the discipline to the budgeted paths and make it structural: hot entry points that neither accept nor return composite temporaries, plus a recorded allocation-per-operation figure checked alongside latency. The rest of the codebase relies on the optimization normally, so the readability cost is paid only where a budget justifies it.

saying these in an interview costs you the question

  • Treats the proof as a guarantee the platform owes the program
  • Bans all allocation across the codebase to protect a few hot paths
  • Relies on a comment asking maintainers not to change a loop
  • Assumes every platform takes the reward the same way
  • Argues the temporary is fine because it is small