Coder Social home page Coder Social logo

polyalloc's Introduction

PolyAlloc - Polymorphic Allocators Practice

Introduction

This repository is dedicated to re-implementing standard polymorphic memory allocators as a means to deepen understanding of memory allocation mechanisms in C++. Polymorphic allocators allow for custom memory management strategies which can be optimized for specific use cases, leading to potentially improved performance and more efficient use of resources.

If you are not familiar with polymorphic memory allocators or the concepts behind them, you may find it helpful to visit this fantastic YouTube playlist: PMR And Allocators. It provides a comprehensive guide that should bring you up to speed with the necessary background to understand the implementations provided in this repository.

Building the Project

To build the project, clone the repository and execute the following commands in your terminal:

mkdir build 
cd build 
cmake ..
cmake --build . -j${nproc}

The following options can be enabled:

  • USE_ASAN : Utilize address sanitizers if available
  • USE_UBSAN : Employ undefined behavior sanitizer if available
  • USE_CLANG_TIDY : Utilize clang-tidy if available
  • USE_CPPCHECK : Employ cppcheck if available
  • BUILD_TESTS : Build Tests

To use these options, execute:

cmake -DBUILD_TESTS=ON -USE_UBSAN=OFF ..
cmake --build . -j$(nproc)

Executing Unit Tests

To run the unit tests, you first need to enable the BUILD_TESTS switch as mentioned above. After the project build is complete, the test executables will be found in the build/tests/ directory. For instance, to run the pool test, use the following command:

cd build 
./tests/tests_pool

Implementations

MonotonicMemoryResource

This is a reimplementation of std::pmr::monotonic_buffer_resource. It allocates from a fixed buffer until it is exhausted, then falls back to an upstream allocator.

Key characteristics:

  • Allocations are served from a fixed buffer until it is exhausted
  • Once exhausted, upstream allocator is used
  • No deallocation supported
  • Satisfies alignment requirements by padding if needed
  • Updates an offset to track progress through buffer

PoolMemoryResource

This is a reimplementation of std::pmr::unsynchronized_pool_resource. It manages a collection of pools, each serving blocks of a fixed size.

Key characteristics:

  • Owns allocated memory, frees on destruction

  • Collection of pools serving different block sizes

  • Each pool manages chunks divided into uniform blocks

    Pool 1:
    Chunk 1:
    [Block][Block]...
    
    Chunk 2: 
    [Block][Block]...
    
  • Allocate dispatches to pool with smallest sufficient block

  • Pool exhaustion triggers new chunk from upstream

  • Largest block size and max chunk size configurable

  • Oversized allocations served directly by upstream

The use of std::max_align_t ensures that the pool's blocks are aligned for any type.

Design

Both resources implement the polymorphic std::pmr::memory_resource interface. This allows them to be used interchangeably with other standard allocators like std::pmr::new_delete_resource.

MonotonicMemoryResource simply manages an offset into a provided buffer, aligning allocations as needed.

PoolMemoryResource maintains a collection of Pool objects, each representing a pool for blocks of a certain size. On allocation, it finds the pool that serves the smallest block size that satisfies the request. The Pool handles chunk allocation from upstream and carving them into blocks.

Example Usage

Here is an example demonstrating usage of the MonotonicMemoryResource:

constexpr int monotonic_buffer_size = 32;
std::array<std::byte, monotonic_buffer_size> buffer{};

memory::MonotonicMemoryResource memory_resource(buffer.data(), monotonic_buffer_size, std::pmr::null_memory_resource());

constexpr int vec_size = 4;
std::pmr::vector<uint32_t> my_vector(vec_size, &memory_resource);

for(unsigned char i=0; i<vec_size; i++){
  my_vector[i] = i+1;
}

This initializes a monotonic_buffer_resource backed by the buffer array. A pmr::vector is then constructed using it which allocates space for 4 elements. std::pmr::null_memory_resource() is the upstream memory resource in this example.

Requirements & Dependencies

A C++20 compiler is required to compile this project, as it utilizes C++20 features like std::format.

This program is self-contained and does not require any third-party libraries for compilation. GoogleTest is used for unit testing and is automatically downloaded by CMake.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.