std.experimental.allocator.building_blocks.bitmapped_block

Types 4

structBitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment, ParentAllocator = NullAllocator, Flag!"multiblock" f = Yes.multiblock)

BitmappedBlock implements a simple heap consisting of one contiguous area of memory organized in blocks, each of size theBlockSize. A block is a unit of allocation. A bitmap serves as bookkeeping data, more precisely one bit per block indicating whether that block is currently allocated or not.

Passing NullAllocator as ParentAllocator (the default) means user code manages allocation of the memory block from the outside; in that case BitmappedBlock must be constructed with a ubyte[] preallocated block and has no responsibility regarding the lifetime of its support underlying storage. If another allocator type is passed, BitmappedBlock defines a destructor that uses the parent allocator to release the memory block. That makes the combination of AllocatorList, BitmappedBlock, and a back-end allocator such as MmapAllocator a simple and scalable solution for memory allocation.

There are advantages to storing bookkeeping data separated from the payload (as opposed to e.g. using AffixAllocator to store metadata together with each allocation). The layout is more compact (overhead is one bit per block), searching for a free block during allocation enjoys better cache locality, and deallocation does not touch memory around the payload being deallocated (which is often cold).

Allocation requests are handled on a first-fit basis. Although linear in complexity, allocation is in practice fast because of the compact bookkeeping representation, use of simple and fast bitwise routines, and caching of the first available block position. A known issue with this general approach is fragmentation, partially mitigated by coalescing. Since BitmappedBlock does not need to maintain the allocated size, freeing memory implicitly coalesces free blocks together. Also, tuning blockSize has a considerable impact on both internal and external fragmentation.

If the last template parameter is set to No.multiblock, the allocator will only serve allocations which require at most theBlockSize. The BitmappedBlock has a specialized implementation for single-block allocations which allows for greater performance, at the cost of not being able to allocate more than one block at a time.

The size of each block can be selected either during compilation or at run time. Statically-known block sizes are frequent in practice and yield slightly better performance. To choose a block size statically, pass it as the blockSize parameter as in BitmappedBlock!(4096). To choose a block size parameter, use BitmappedBlock!(chooseAtRuntime) and pass the block size to the constructor.

Parameters

theBlockSizethe length of a block, which must be a multiple of theAlignment
theAlignmentalignment of each block
ParentAllocatorallocator from which the BitmappedBlock will draw memory. If set to NullAllocator, the storage must be passed via the constructor
fYes.multiblock to support allocations spanning across multiple blocks and No.multiblock to support single block allocations. Although limited by single block allocations, No.multiblock will generally provide higher performance.
structSharedBitmappedBlock(size_t theBlockSize, uint theAlignment = platformAlignment, ParentAllocator = NullAllocator, Flag!"multiblock" f = Yes.multiblock)

The threadsafe version of the BitmappedBlock. The semantics of the SharedBitmappedBlock are identical to the regular BitmappedBlock.

Parameters

theBlockSizethe length of a block, which must be a multiple of theAlignment
theAlignmentalignment of each block
ParentAllocatorallocator from which the BitmappedBlock will draw memory. If set to NullAllocator, the storage must be passed via the constructor
fYes.multiblock to support allocations spanning across multiple blocks and No.multiblock to support single block allocations. Although limited by single block allocations, No.multiblock will generally provide higher performance.
structBitmappedBlockWithInternalPointers( size_t theBlockSize, uint theAlignment = platformAlignment, ParentAllocator = NullAllocator)

A BitmappedBlock with additional structure for supporting resolveInternalPointer. To that end, BitmappedBlockWithInternalPointers adds a bitmap (one bit per block) that marks object starts. The bitmap itself has variable size and is allocated together with regular allocations.

The time complexity of resolveInternalPointer is k, where k is the size of the object within which the internal pointer is looked up.

Fields
private BitmappedBlock!(theBlockSize, theAlignment, ParentAllocator) _heap
private BitVector _allocStart
Methods
private bool ensureRoomForAllocStart(size_t len) @safe
size_t goodAllocSize(size_t n) pure nothrow @safe @nogcDitto
void[] allocate(size_t bytes)Ditto
void[] allocateAll()Ditto
bool expand(ref void[] b, size_t bytes)Ditto
bool deallocate(void[] b)Ditto
Ternary resolveInternalPointer(const void * p, ref void[] result) nothrow @safe @nogcDitto
Ternary empty()Ditto
private void markAllAsUnused()
private bool markAsUsed(void[] b)
private void doneMarking()
private structBitVector
Fields
ulong[] _rep
Methods
auto rep(this _)()
void opSliceAssign(bool b) pure nothrow @safe @nogc
void opSliceAssign(bool b, ulong x, ulong y) pure nothrow @safe @nogc
bool opIndex(ulong x) pure nothrow @safe @nogc
void opIndexAssign(bool b, ulong x) pure nothrow @safe @nogc
ulong length() pure nothrow @safe @nogc const
ulong find1(ulong i) pure nothrow @safe @nogc
ulong find1Backward(ulong i) pure nothrow @safe @nogc
bool allAre0() pure nothrow @safe @nogc constAre all bits zero?
bool allAre1() pure nothrow @safe @nogc constAre all bits one?
ulong findZeros(immutable size_t howMany, ulong start) pure nothrow @safe @nogc
Constructors
this(ulong[] data)

Functions 5

private fnuint leadingOnes(ulong x) pure nothrow @safe @nogcReturns the number of most significant ones before a zero can be found in `x`. If `x` contains no zeros (i.e. is equal to `ulong.max`), returns 64.
private fnuint findContigOnes(ulong x, uint n) pure nothrow @safe @nogcFinds a run of contiguous ones in `x` of length at least `n`.
private fnvoid setBits(ref ulong w, uint lsb, uint msb) pure nothrow @safe @nogc
private fnbool setBitsIfZero(ref ulong w, uint lsb, uint msb) pure nothrow @safe @nogc
private fnvoid resetBits(ref ulong w, uint lsb, uint msb) pure nothrow @safe @nogc