TL;DR
- PMR is worth watching after C++17 because database systems create many short-lived small objects.
- PMR solves a different problem from smart pointers. Smart pointers describe ownership; PMR describes allocation locality and lifetime grouping.
- Important boundary: I did not see heavy PMR use in the DuckDB snapshot I checked. This is a design direction, not a claim about current implementation.
What PMR asks
PMR means std::pmr, or polymorphic memory resource. It is part of C++17.
It does not mainly ask:
Who owns this object?
Smart pointers already answer that.
PMR asks:
Many small objects and containers have the same lifetime.
Where should their memory come from?
That question is very natural in a database system.
Where the pattern appears
Database systems often build short-lived structures:
- temporary expression lists in the binder
- optimizer join graphs
- rule rewrite nodes
- candidate plans and paths
- query-local metadata
- debug and reporting structures
These objects often die together when the query or optimizer phase ends.
With ordinary std::vector, std::unordered_map, and std::string, each container uses the default allocator. Many small allocations can become scattered and harder to account for.
PMR lets containers share one memory resource:
std::pmr::monotonic_buffer_resource arena;
std::pmr::vector<Node *> nodes{&arena};
std::pmr::unordered_map<int, Cost> costs{&arena};
std::pmr::string label{&arena};
This is somewhat like a C++ version of PostgreSQL's MemoryContext, but it composes more naturally with STL containers.
PMR versus smart pointers
Smart pointers describe ownership:
Who destroys this object?
PMR describes allocation grouping:
These objects belong to one query.
These objects belong to one optimizer phase.
These objects can be released together.
The tools solve different problems:
| Problem | Better tool |
|---|---|
| Single-object ownership | unique_ptr |
| Resource cleanup | RAII |
| Many small short-lived objects | PMR |
| Region lifetime in PostgreSQL C code | MemoryContext |
Do not put it everywhere
PMR should not be applied mechanically.
DuckDB already has careful execution memory layouts: Vector, DataChunk, validity masks, selection vectors, string heaps, buffer manager state, and hash table payloads. These are close to the hot path.
Whether PMR helps there depends on code generation, cache locality, memory accounting, and the existing memory manager.
A more reasonable starting point is:
Use it first for parser, binder, optimizer, and debug structures.
Be careful before moving it into execution hot paths.
Do not bypass the existing memory manager or buffer manager.
PMR is useful because it matches a database lifetime pattern. It is not useful merely because it is modern C++.