C++17's std::pmr: A Deep Dive into Costs and Considerations
0:10 Introduction: David Sankel introduces std::pmr (polymorphic memory resource) and highlights its costs, particularly in large codebases.
1:39 Problem Space: Sankel outlines the problems std::pmr addresses: slow allocation, fragmentation hurting performance, and overly complex pre-C++17 allocators.
5:04 Memory Resources: Three new memory resources are introduced: synchronized pool (for frequently accessed data), unsynchronized pool (for multi-threaded scenarios without synchronization needs), and monotonic buffer (for high-speed allocation at the expense of space).
7:53 Simplicity and Logging Resource: Sankel demonstrates the relative simplicity of creating a new memory resource by implementing a LoggingResource that logs allocation events.
10:08 Setting Default Resource: He emphasizes that setting the default resource requires global lifetime to avoid undefined behavior due to static variables in other parts of the code being deallocated later.
18:12 Example: Basic Allocation with PMR: Using a simple Foo and Bar class example, Sankel illustrates how to make classes allocator-aware to leverage std::pmr.
20:14 Undefined Behavior with Mismatched Allocators: He stresses that using standard unique_ptr with custom allocators leads to undefined behavior, highlighting the need for careful management.
24:59 Exception Safety: Exception handling is crucial when using custom allocation, as demonstrated with a try-catch block to prevent memory leaks if construction throws.
36:14 PMR Strings and Small Buffer Optimization: Switching to std::pmr::string can increase object size even without noticeable allocations due to the small buffer optimization.
42:33 Allocator Awareness Best Practices: Sankel provides a list of best practices, including fixing allocators at construction, passing allocator arguments to constructors, using the "dirty little secret" move constructor, defining an allocator type member, and using global storage for default allocators.
51:23 Move Semantics and The Dirty Little Secret: He delves into the impact of std::pmr on move semantics, explaining the need for a special noexcept move constructor (the "dirty little secret") to avoid copies during vector resizing and maintain strong exception safety.
57:31 Increased Object Size: The "dirty little secret" can lead to increased object size due to multiple allocator copies, potentially affecting cache performance.
1:01:07 More Best Practices for Allocator Storage: Sankel suggests delegating allocator storage to data members to minimize redundancy and reduce object size.
1:03:13 Move Semantics and Return Values: He discusses the challenges of returning allocator-aware objects, noting that the returned object's allocator might not match the caller's expectation. Several options for managing this are presented, but none are deemed ideal.
1:10:41 Impact on Existing Code: Sankel cautions that using std::pmr can make seemingly safe code (like moving data members) potentially unsafe due to the "dirty little secret" and the potential for dangling pointers.
1:13:55 Development Costs and Boilerplate: He points out that making an entire codebase allocator-aware introduces significant development costs due to the extensive boilerplate required.
1:15:13 Spotty Standard Support: Some standard types, like std::variant and std::function, lack allocator support, hindering widespread adoption.
1:17:28 Alternatives to PMR: Sankel proposes alternatives to std::pmr, including object pools and custom data types tailored to specific memory access patterns.
1:19:01 When to Use PMR: He expresses his opinion that custom data types often offer better performance and lower overall cost compared to making an entire codebase allocator-aware with std::pmr. He suggests that std::pmr is best suited for situations where performance is critical and you cannot write custom types, or as a blunt instrument for quick performance gains in already allocator-aware code.
1:23:01 Instrumentation Benefits: John Lakos highlights the benefits of using allocators for instrumentation and debugging, particularly with tools like TCmalloc.
1:29:19 Value Proposition of Allocators: Lakos summarizes the three main values of allocators: performance, object placement, and instrumentation.
1:31:24 Thread-Local Allocators: The discussion touches upon thread-local allocators and metaclasses as potential future avenues for managing allocation more effectively.