1.8 kB
Design Notes#
Performance Impact of Boxing Futures#
future_form uses BoxFuture and LocalBoxFuture under the hood. This section discusses the performance implications of that choice.
Costs#
Allocation
- One heap allocation per boxed future (typically small, but adds up in hot paths)
- Deallocation when the future completes
Indirection
- Virtual dispatch through the
dyn Futuretrait object on each poll - Pointer chasing can hurt CPU cache locality
In Practice#
The impact is often negligible because:
- Futures are usually polled relatively few times compared to the work they represent
- A single network call or disk read dwarfs the cost of one allocation
- The allocator is highly optimized for small, short-lived allocations
When It Matters#
- Tight loops spawning thousands of tiny futures
- Latency-critical code paths (microsecond-level)
- Embedded/
no_stdenvironments with constrained allocators
Alternatives#
| Approach | Tradeoff |
|---|---|
async-trait |
Same cost (also boxes) |
impl Future (static dispatch) |
Avoids boxing but can't be used in trait objects or with this kind of abstraction |
| Enum-based dispatch | Works for a fixed set of variants, but doesn't generalize |
Recommendation#
For most async code doing I/O, the boxing cost is noise. If profiling shows it's a bottleneck, you'd typically avoid the abstraction entirely in that hot path rather than try to optimize the boxing.