stdx.allocator.building_blocks.quantizer

  • Declaration

    struct Quantizer(ParentAllocator, alias roundingFunction);

    This allocator sits on top of and quantizes allocation sizes, usually from arbitrary positive numbers to a small set of round numbers (e.g. powers of two, page sizes etc). This technique is commonly used to:

    Discussion

    • Preallocate more memory than requested such that later on, when reallocation is needed (e.g. to grow an array), expansion can be done quickly in place. Reallocation to smaller sizes is also fast (in-place) when the new size requested is within the same quantum as the existing size. Code that's reallocation-heavy can therefore benefit from fronting a generic allocator with a . These advantages are present even if does not support reallocation at all.
    • Improve behavior of allocators sensitive to allocation sizes, such as and . Rounding allocation requests up makes for smaller free lists/trees at the cost of slack memory (internal fragmentation).


    The following methods are forwarded to the parent allocator if present: , , , .

    Preconditions: must satisfy three constraints. These are not enforced (save for the use of ) for the sake of efficiency.

    1. for all of type ;
    2. must be monotonically increasing, i.e. for all ;
    3. must be , i.e. always return the same value for a given .

    Examples

    1. import stdx.allocator.building_blocks.free_tree : FreeTree; import stdx.allocator.gc_allocator : GCAllocator; size_t roundUpToMultipleOf(size_t s, uint base) { auto rem = s % base; return rem ? s + base - rem : s; } // Quantize small allocations to a multiple of cache line, large ones to a // multiple of page size alias MyAlloc = Quantizer!( FreeTree!GCAllocator, n => roundUpToMultipleOf(n, n <= 16_384 ? 64 : 4096)); MyAlloc alloc; const buf = alloc.allocate(256); assert(buf.ptr);

    • Declaration

      ParentAllocator parent;

      The parent allocator. Depending on whether holds state or not, this is a member variable or an alias for ParentAllocator.instance.

    • Declaration

      size_t goodAllocSize(size_t n);

      Returns .

    • Declaration

      enum auto alignment;

      Alignment is identical to that of the parent.

    • Declaration

      void[] allocate(size_t n);

      Gets a larger buffer by calling . If is , returns . Otherwise, returns .

    • Declaration

      void[] alignedAllocate(size_t n, uint);

      Defined only if exists and works similarly to by forwarding to .

    • Declaration

      bool expand(ref void[] b, size_t delta);

      First checks whether there's enough slack memory preallocated for by evaluating . If that's the case, expands in place. Otherwise, attempts to use appropriately if present.

    • Declaration

      bool reallocate(ref void[] b, size_t s);

      Expands or shrinks allocated block to an allocated size of . Expansion occurs in place under the conditions required by . Shrinking occurs in place if .

    • Declaration

      bool alignedReallocate(ref void[] b, size_t s, uint a);

      Defined only if exists. Expansion occurs in place under the conditions required by . Shrinking occurs in place if .

    • Declaration

      bool deallocate(void[] b);

      Defined if exists and forwards to .