Summary
Introduce support for user-provided/custom allocators throughout the Morpheus codebase to enable greater control over memory management, performance tuning, and integration with specialised runtime environments.
Motivation
Morpheus is increasingly being used in performance-critical and resource-constrained environments (e.g. low-latency systems, high-throughput pipelines, and custom runtime contexts). In such domains, the ability to control memory allocation strategies is essential.
Currently, Morpheus relies on default allocation mechanisms (e.g. new, std::allocator), which imposes several limitations:
-
Lack of control over allocation strategy
Users cannot plug in arena allocators, pool allocators, or monotonic buffers to reduce allocation overhead or fragmentation.
-
Performance constraints
High-frequency allocations in hot paths (e.g. parsing, transformations, container usage) may introduce unnecessary latency and cache inefficiencies.
-
Integration limitations
Many systems (game engines, trading systems, embedded platforms) require allocations to go through custom memory subsystems for tracking, alignment, or safety guarantees.
-
Testing and instrumentation
Custom allocators enable better observability (allocation tracking, leak detection, failure injection), which is currently difficult to achieve.
Proposal
Introduce allocator-awareness across relevant Morpheus components, following established C++ practices:
1. Allocator-aware types
2. Propagation and consistency
3. PMR support (optional but recommended)
4. Default behaviour remains unchanged
Design Considerations
-
Header/module boundaries
Care must be taken to ensure allocator types are correctly exported across module interfaces.
-
ABI impact
Introducing allocator template parameters may affect ABI stability; changes should be scoped to avoid breaking consumers where possible.
-
Complexity vs benefit
Allocator support should be introduced incrementally, prioritising:
- Frequently used containers
- Performance-critical paths
-
Monadic/functional components
For parts of Morpheus using monadic patterns, ensure allocator usage does not overly complicate value semantics or chaining.
Alternatives Considered
-
Global allocator hooks
Rejected due to lack of composability and poor isolation between components.
-
Hardcoded custom allocators
Too restrictive; does not allow users to integrate their own memory strategies.
Benefits
- Improved performance in allocation-heavy workloads
- Better integration with specialised systems
- Enhanced testing and debugging capabilities
- Greater flexibility for library users without impacting default usability
Potential Next Steps
- Identify core types that would benefit most from allocator support
- Prototype allocator-aware container(s)
- Evaluate PMR integration
- Document allocator usage patterns for users
Open Questions
- Should PMR be the primary abstraction, or an optional layer?
- Which components should be prioritised for initial support?
- Do we need allocator-aware APIs, or just allocator-aware types?
Summary
Introduce support for user-provided/custom allocators throughout the Morpheus codebase to enable greater control over memory management, performance tuning, and integration with specialised runtime environments.
Motivation
Morpheus is increasingly being used in performance-critical and resource-constrained environments (e.g. low-latency systems, high-throughput pipelines, and custom runtime contexts). In such domains, the ability to control memory allocation strategies is essential.
Currently, Morpheus relies on default allocation mechanisms (e.g.
new,std::allocator), which imposes several limitations:Lack of control over allocation strategy
Users cannot plug in arena allocators, pool allocators, or monotonic buffers to reduce allocation overhead or fragmentation.
Performance constraints
High-frequency allocations in hot paths (e.g. parsing, transformations, container usage) may introduce unnecessary latency and cache inefficiencies.
Integration limitations
Many systems (game engines, trading systems, embedded platforms) require allocations to go through custom memory subsystems for tracking, alignment, or safety guarantees.
Testing and instrumentation
Custom allocators enable better observability (allocation tracking, leak detection, failure injection), which is currently difficult to achieve.
Proposal
Introduce allocator-awareness across relevant Morpheus components, following established C++ practices:
1. Allocator-aware types
Update core containers and data structures to accept an allocator template parameter where appropriate.
Follow the standard library model:
2. Propagation and consistency
Ensure allocators propagate correctly through:
Align with
std::allocator_traitssemantics.3. PMR support (optional but recommended)
Consider providing support for
std::pmr:std::pmr::polymorphic_allocatorstd::pmr::memory_resourceThis allows runtime-configurable allocation strategies without templating explosion.
4. Default behaviour remains unchanged
Preserve current behaviour by default:
std::allocator.Ensure zero-cost abstraction where possible.
Design Considerations
Header/module boundaries
Care must be taken to ensure allocator types are correctly exported across module interfaces.
ABI impact
Introducing allocator template parameters may affect ABI stability; changes should be scoped to avoid breaking consumers where possible.
Complexity vs benefit
Allocator support should be introduced incrementally, prioritising:
Monadic/functional components
For parts of Morpheus using monadic patterns, ensure allocator usage does not overly complicate value semantics or chaining.
Alternatives Considered
Global allocator hooks
Rejected due to lack of composability and poor isolation between components.
Hardcoded custom allocators
Too restrictive; does not allow users to integrate their own memory strategies.
Benefits
Potential Next Steps
Open Questions