12.4 Performance Considerations
Rust closures provide strong performance characteristics:
- No Hidden Heap Allocations: Closure objects (the implicit struct holding captured data) typically live on the stack if their size is known at compile time. They are not automatically heap-allocated unless explicitly placed in a
Box
or other heap-based container. - Zero-Cost Abstraction (Generics): When closures are passed using generics (
impl Fn...
), the compiler performs monomorphization, generating specialized code for each closure type. This allows inlining the closure body, resulting in performance equivalent to a direct function call. There is usually no runtime overhead. - Dynamic Dispatch (
dyn Fn...
): Using trait objects (Box<dyn Fn()>
,&dyn FnMut()
, etc.) allows storing different closure types together but introduces:- A small runtime cost for vtable lookup (like C++ virtual functions).
- Heap allocation if using
Box<dyn Fn...>
. This offers flexibility at the expense of some performance.
For performance-critical code, prefer generics (impl Fn...
) over trait objects (dyn Fn...
) to leverage static dispatch and inlining.