Should new C++ code use memory resources instead of allocators?
Asked Answered
C

1

33

C++17 will bring us std::pmr::memory_resource which is a clean interface for allocating and deallocating memory. Unlike the Allocator concept, it does just that and nothing more. There will also be std::pmr::polymorphic_allocator which wraps a memory resource into a classical allocator so it can be used with existing containers.

If I'm about to write a new container (or other memory-hungry) type targeting C++17 and later, should I continue programming against the Allocator concept or rather use the newer and cleaner abstraction directly?

As of now, my thoughts go like this.

Reasons to continue using allocators:

  • It is consistent with the standard library and existing code. Even the new std::pmr::* container aliases continue to use allocators.
  • Since a memory resource can be wrapped into a std::pmr::polymorphic_allocator, the allocator interface is more general and satisfies the needs of more clients.
  • Memory resources always use run-time polymorphism so they have a minor additional run-time overhead compared to the zero-overhead abstraction that allocators can provide.
  • Maybe somebody actually needs the other parts of the allocator interface (such as custom pointer types) which cannot be provided by a pure memory resource.

Reasons to start using memory resources instead of allocators:

  • The allocator interface is clunky and hard to implement. The std::pmr::memory_resource interface is clean and straight-forward.
  • Since memory resources are polymorphic, they don't affect the type of the container which means fewer template instantiations (and therefore maybe faster compiles and smaller executables) and enables us to move more code into separate translation units.
  • If an object uses a memory resource, it can always instantiate a sub-object that still uses allocators by wrapping the memory resource into a std::pmr::polymorphic_allocator. The other way round is more difficult.
  • Memory allocation is a relatively work-intensive task anyway. A single virtual function call doesn't add much overhead, relatively speaking.

Do there already exist any recommendations for how to use the new library feature effectively?

Campanology answered 30/9, 2016 at 19:49 Comment(3)
The allocator interface isn't actually all that hard to implement. C++11 made it a lot simpler. You need like two type names, two functions and two comparisons.Dorinda
Whether memory allocation is "relatively work intensive" depends on the allocator, doesn't it? If it allocates from a monotonic arena on the local stack, it might not be terribly expensive and quite inlinable.Dorinda
@KerrekSB That's true. Actually, I never implemented it without the adapters provided by C++11. Still, it is not what I'd consider elegant.Campanology
C
13

At this point no.

Allocators in C++ currently are much easier than they used to be.

They provide both pmr (polymorphic) and classic allocator support.

More importantly, pmr based allocation has not been in heavy use for years. Any weaknesses may still come to light.

Fast pool based allocators, or even fixed buffer ones or sbo (small buffer optimization) extensions, may notice the virtualization overhead.

Clarkia answered 30/9, 2016 at 20:20 Comment(1)
Would it make sense, though, for people writing containers to use the polymorphic byte allocator as the default? It makes sense to want to be able to pick an allocator at compile time, but for general purpose it seem a like pmr is a reasonable default.Onetoone

© 2022 - 2024 — McMap. All rights reserved.