Coder Social home page Coder Social logo

ilanbenyona-dev / cppshift-memorypool Goto Github PK

View Code? Open in Web Editor NEW

This project forked from devshiftteam/appshift-memorypool

0.0 0.0 0.0 1.22 MB

A very fast cross-platform memory pool mechanism for C++ built using a data-oriented approach (8 to 24 times faster than regular new or delete, depending on operating system & compiler)

License: Apache License 2.0

CMake 1.17% C++ 98.83%

cppshift-memorypool's Introduction

MemoryPool For C++

A very fast cross-platform memory pool mechanism for C++ built using a data-oriented approach. I hope this simple feature will help you increase your software's performance - and there are more projects and features to come under the CPPShift library name, wait for it ;)

Table of Contents

Usage

To use the memory pool features you just need to copy the MemoryPool.cpp, MemoryPool.h & MemoryPoolData.h files to your project. The memory pool structure is CPPShift::Memory::MemoryPool. The Memory Pool Is Not Thread Safe - In case of threads it is better to create a memory pool for each thread

  • Create a memory pool: CPPShift::Memory::MemoryPool * mp = new CPPShift::Memory::MemoryPool(size); Create a new memory pool structure and a first memory block. If you don't specify a size then by default it will be the MEMORYPOOL_DEFAULT_BLOCK_SIZE macro.
  • Allocate space: Type* allocated = new (mp) Type[size]; or Type* allocated = (Type*) mp->allocate(size * sizeof(Type)); or Type* allocated = mp->allocate<Type>(size); Where Type is the object\primitive type to create, mp is the memory pool object address, and size is a represention of the amount of types to allocate.
  • Deallocate space: mp->free(allocated) Remove an allocated space
  • Reallocate space: Type* allocated = mp->reallocate<Type>(allocated, size); or Type* allocated = (Type*) mp->reallocate(allocated, size); Rellocate a pre-allocated space, will copy the previous values to the new memory allocated.
  • Dump data of a memory pool: mp->dumpPoolData() This function prints outs the data about the blocks and units in the pool.

Memory scoping

Scoping is a fast way to deallocate many allocations at once. If for example you need to allocate more than once in a given part of the code, and then you deallocate all the allocations that happaned, then you can "scope" all these allocations together. it works the same way as a stack in a function scope.

  • Start A Scope: mp->startScope() where mp is the memory pool structure. This function creates a "checkpoint" of the offset and block in the memory pool.
  • End A Scope: mp->endScope() Will free all the allocations made after the scope started.
  • Scope Inside A Scope: You can nest scopes inside scopes by strating a new scope again, just the same way that the stack works with function scopes. Each scope is pointing to the previous one to create a chain that allows the memory pool manager to manage scope nesting.

Macros

There are some helpful macros available to indicate how you want the MemoryPool to manage your memory allocations.

  • #define MEMORYPOOL_DEFAULT_BLOCK_SIZE 1024 * 1024: The MemoryPool allocates memory into blocks, each block can have a maximum size avalable to use - when it exceeds this size, the MemoryPool allocates a new block - use this macro to define the maximum size to give to each block. By default the value is 1024 * 1024 which is 1MB.

Methodology

The MemoryPool is a structure pointing to the start of a chain of blocks, which size of every block is by default MEMORYPOOL_BLOCK_MAX_SIZE macro (See Macros) or the size passed into the CPPShift::Memory::MemoryPool(size) constructor. The MemoryPool is an object holding the necessary functions to work with the a memory pool. What's also good is that you can also access the MemoryPool structure data directly if needed (everything is public).

MemoryPool data (MemoryPool)

The memory pool structure holds meta-data about the memory space that is allocated and stored in the pool.

  • SMemoryBlockHeader* firstBlock; - Holds the first block in the chain of memory blocks.
  • SMemoryBlockHeader* currentBlock; - Holds the last block in the chain that is used first for allocating (allocations are happening in a stack manner, where each memory unit allocated is on top of the previous one, when a block reaches it's maximum size then a new block is allocated and added to the block chain of the pool).
  • size_t defaultBlockSize; - Default size to use when creating a new block, the size is defined by the MEMORYPOOL_BLOCK_MAX_SIZE macro or by passing the size as a parameter for the CPPShift::Memory::MemoryPoolManager::create(size) function.
  • SMemoryScopeHeader* currentScope; - A pointer to the current scope in the memory pool.

Memory Block (SMemoryBlockHeader)

Each block contains a block header the size of 48 bytes containing the following information:

  • size_t blockSize; - Size of the block
  • size_t offset; - Offset in the block from which the memory is free (The block is filled in sequencial order)
  • SMemoryBlockHeader* next; - Pointer to the next block
  • SMemoryBlockHeader* prev; - Pointer to the previous block
  • size_t numberOfAllocated - Number of units currently allocated in this block. Helps smart garbage collection when block data has been freed.
  • size_t numberOfDeleted - Number of units that have been flaged as deleted. The system removes blocks by comparing the deleted with the allocated.

When a block is fully filled the MemoryPool creates a new block and relates it to the previous block, and the previous to the current, them uses the new pool as the current block.

Memory Unit (SMemoryUnitHeader)

When allocating a space, MemoryPool creates a SMemoryUnitHeader and moves the blocks offset forward by the header size plus the amount of space requested. The header is 16 bytes long and contains the following data:

  • size_t length; - The length in bytes of the allocated space
  • SMemoryBlockHeader* container - Block which this unit belongs to

Memory Scope (SMemoryScopeHeader)

A scope has it's own structure - it has an offset and a pointer to the starting block of the scope, and also a pointer to the previous scope (parent).

  • size_t scopeOffset; - Saves the offset of the block when start scope is declared.
  • SMemoryBlockHeader* firstScopeBlock; - Saves the current block when a start scope is declared, helps to know until which block to free everything when the scope ends.
  • SMemoryScopeHeader* prevScope; - Pointer to the previous scope/NULL if no parent scope is present.

Benchmark

Windows & CLang


About 21-24 times faster than standard new/delete in each test.

Windows & MSVC


About 10-13 times faster than standard new/delete in each test.

MacOS & CLang


About 8-10 times faster than standard new/delete in each test.

About

  • Sapir Shemer is the proud business owner of DevShift and an Open-Source enthusiast. Have been programming since the age of 7. Mathematics Student :)

Contributors - Thank You! :D

A list of people that were kind enough to help:

More to come in later versions

In the next versions I'm planning to add some interesting features:

  • Ability to put thread safety on the memory pool to make a thread shared memory pool.
  • Ability to create an inter-process memory pool which can be shared between different processes.
  • compressGarbage(): Will compress deleted units that are next to eachother into one unit.

cppshift-memorypool's People

Contributors

lesscomplexity avatar sagiweizmann avatar

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.