Search code examples
c++cachingbooststlmake-shared

Data cache implications of using std::make_shared()


I read here that:

make_shared is (in practice) more efficient, because it allocates the reference control block together with the actual object in one single dynamic allocation. By contrast, the constructor for shared_ptr that takes a naked object pointer must allocate another dynamic variable for the reference count

Does it mean that vector of std::shared_ptr created using std::make_shared will be "cache-friendly" as the data (control block and real pointer's data) are in one chunk ?

My use case is a vector of 100 000 shared pointers where object pointed to is 14 bytes.


Solution

  • Maybe, but don't count on it.

    For cache-friendliness, you want to use as little memory as possible, and you want operations that are close together in address to also be close together in time (that is, close enough that the second operation uses memory that is still in some level of cache from the effects of the first operation: the lower the level of cache the better).

    If you use make_shared, then there might well be a slight saving in total memory use, which at least tends to be a win for the cache no matter what your memory usage pattern.

    If you use make_shared, then the control block and the object referred to (referand) will be adjacent in memory.

    If you don't use make_shared, and your objects are a different size from your control blocks, then with common memory allocators there's a reasonable chance that the objects will be clustered together in one place and the control blocks clustered together in a different place. If they are the same size (once rounded by the memory allocator in some implementation-specific way), then with common memory allocators there's a reasonable chance that they'll just alternate in memory for long runs unless shared_ptr does something to affect that.

    Your memory access pattern will determine which of those layouts is better for the cache -- and of course the actual layout you get in the non-make_shared case might be something else again, depending on implementation details.

    The fact that you have a vector is basically independent of all this, since the shared_ptr objects are separate from the control-blocks and the referands.