std::any
and Small Object Optimization
Does std::any
use small object optimization? If so, how does it work and what are the benefits?
Yes, most standard library implementations of std::any use a technique called "small object optimization" (SOO).
The idea behind SOO is that for small types (typically smaller than the size of two or three pointers), it's more efficient to store the object directly inside the std::any
object, rather than allocating it on the heap.
Here's roughly how it works:
- The
std::any
has a member variable that's a union of a pointer and an array of chars. - If the type stored is small enough, it's placement-new'ed into the char array.
- If the type is too large, it's allocated on the heap and the pointer in the union is set to point to it.
- A separate member variable stores the size of the stored type, which is used to determine whether the union holds a pointer or an object.
The benefits of this technique are:
- Improved performance: Allocating memory on the heap is relatively expensive. By avoiding this for small types, SOO can significantly improve the performance of creating and copying
std::any
objects. - Reduced memory overhead: Without SOO, every
std::any
would need to store a pointer, which is 4 or 8 bytes on most systems. For small types, this can be a significant overhead. SOO reduces this overhead. - Better cache locality: Objects stored directly in the
std::any
are more likely to be in the CPU's cache when they're accessed, which can improve performance.
However, it's important to note that SOO is an implementation detail. The C++ standard doesn't require it, and the exact details (like the size threshold for "small" types) can vary between implementations.
As a user of std::any
, you don't need to worry about SOO - it's all handled automatically. But it's a good example of the kind of low-level optimizations that go into making standard library types efficient.
Unconstrained Dynamic Types using Void Pointers and std::any
Learn how to use void pointers and std::any
to implement unconstrained dynamic types, and understand when they should be used