stdx.allocator.building_blocks.stats_collector

Allocator that collects useful statistics about allocations, both global and per calling point. The statistics collected can be configured statically by choosing combinations of Options appropriately.

Example:

  1. import stdx.allocator.gc_allocator : GCAllocator; import stdx.allocator.building_blocks.free_list : FreeList; alias Allocator = StatsCollector!(GCAllocator, Options.bytesUsed);

  • Declaration

    enum Options: ulong;

    Options for defined below. Each enables during compilation one specific counter, statistic, or other piece of information.

    • Declaration

      numOwns

      Counts the number of calls to .

    • Declaration

      numAllocate

      Counts the number of calls to . All calls are counted, including requests for zero bytes or failed requests.

    • Declaration

      numAllocateOK

      Counts the number of calls to that succeeded, i.e. they returned a block as large as requested. (N.B. requests for zero bytes count as successful.)

    • Declaration

      numExpand

      Counts the number of calls to , regardless of arguments or result.

    • Declaration

      numExpandOK

      Counts the number of calls to that resulted in a successful expansion.

    • Declaration

      numReallocate

      Counts the number of calls to , regardless of arguments or result.

    • Declaration

      numReallocateOK

      Counts the number of calls to that succeeded. (Reallocations to zero bytes count as successful.)

    • Declaration

      numReallocateInPlace

      Counts the number of calls to that resulted in an in-place reallocation (no memory moved). If this number is close to the total number of reallocations, that indicates the allocator finds room at the current block's end in a large fraction of the cases, but also that internal fragmentation may be high (the size of the unit of allocation is large compared to the typical allocation size of the application).

    • Declaration

      numDeallocate

      Counts the number of calls to .

    • Declaration

      numDeallocateAll

      Counts the number of calls to .

    • Declaration

      numAll

      Chooses all flags.

    • Declaration

      bytesUsed

      Tracks bytes currently allocated by this allocator. This number goes up and down as memory is allocated and deallocated, and is zero if the allocator currently has no active allocation.

    • Declaration

      bytesAllocated

      Tracks total cumulative bytes allocated by means of , , and (when resulting in an expansion). This number always grows and indicates allocation traffic. To compute bytes deallocated cumulatively, subtract from .

    • Declaration

      bytesExpanded

      Tracks the sum of all values in calls of the form that succeed (return ).

    • Declaration

      bytesContracted

      Tracks the sum of all with in calls of the form that succeed (return ). In per-call statistics, also unambiguously counts the bytes deallocated with .

    • Declaration

      bytesMoved

      Tracks the sum of all bytes moved as a result of calls to that were unable to reallocate in place. A large number (relative to ) indicates that the application should use larger preallocations.

    • Declaration

      bytesNotMoved

      Tracks the sum of all bytes NOT moved as result of calls to that managed to reallocate in place. A large number (relative to ) indicates that the application is expansion-intensive and is saving a good amount of moves. However, if this number is relatively small and is high, it means the application is overallocating for little benefit.

    • Declaration

      bytesSlack

      Measures the sum of extra bytes allocated beyond the bytes requested, i.e. the . This is the current effective number of slack bytes, and it goes up and down with time.

    • Declaration

      bytesHighTide

      Measures the maximum bytes allocated over the time. This is useful for dimensioning allocators.

    • Declaration

      bytesAll

      Chooses all flags.

    • all

      Declaration

      all

      Combines all flags above.

  • Declaration

    struct StatsCollector(Allocator, ulong flags = Options.all, ulong perCallFlags = 0);

    Allocator that collects extra data about allocations. Since each piece of information adds size and time overhead, statistics can be individually enabled or disabled through compile-time .

    Discussion

    All stats of the form record counts of events occurring, such as calls to functions and specific results. The stats of the form collect cumulative sizes.

    In addition, the data , , , , and is associated with each specific allocation. This data prefixes each allocation.

    Examples

    1. import stdx.allocator.building_blocks.free_list : FreeList; import stdx.allocator.gc_allocator : GCAllocator; alias Allocator = StatsCollector!(GCAllocator, Options.all, Options.all); Allocator alloc; auto b = alloc.allocate(10); alloc.reallocate(b, 20); alloc.deallocate(b); static if (__VERSION__ >= 2073) { import std.file : deleteme, remove; import std.range : walkLength; import std.stdio : File; auto f = deleteme ~ "-dlang.stdx.allocator.stats_collector.txt"; scope(exit) remove(f); Allocator.reportPerCallStatistics(File(f, "w")); alloc.reportStatistics(File(f, "a")); assert(File(f).byLine.walkLength == 22); }

    • Declaration

      Allocator parent;

      The parent allocator is publicly accessible either as a direct member if it holds state, or as an alias to Allocator.instance otherwise. One may use it for making calls that won't count toward statistics collection.

    • Declaration

      alias alignment = Allocator.alignment;

      Alignment offered is equal to .

    • Declaration

      Ternary owns(void[] b);

      Increments (per instance and and per call) and forwards to .

    • Declaration

      void[] allocate(size_t n);

      Forwards to . Affects per instance: , , , , , and . Affects per call: , , and .

    • Declaration

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

      Defined whether or not is defined. Affects per instance: , , , , , and . Affects per call: , , , and .

    • Declaration

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

      Defined whether or not is defined. Affects per instance: , , , , , , , and . Affects per call: , , , , , , and .

    • Declaration

      bool deallocate(void[] b);

      Defined whether or not is defined. Affects per instance: , , and . Affects per call: and .

    • Declaration

      bool deallocateAll();

      Defined only if is defined. Affects per instance and per call .

    • Declaration

      Ternary empty();

      Defined only if is defined. Returns .

    • Declaration

      void reportStatistics(R)(auto ref R output);

      Reports per instance statistics to (e.g. ). The format is simple: one kind and value per line, separated by a colon, e.g.

    • Declaration

      struct PerCallStatistics;

      Defined if is nonzero.

      • Declaration

        string file;
        uint line;

        The file and line of the call.

      • Declaration

        Options[] opts;

        The options corresponding to the statistics collected.

      • Declaration

        ulong[] values;

        The values of the statistics. Has the same length as .

      • Declaration

        const string toString();

        Format to a string such as: .

    • Declaration

      static auto byFileLine();

      Defined if is nonzero. Iterates all monitored file/line instances. The order of iteration is not meaningful (items are inserted at the front of a list upon the first call), so preprocessing the statistics after collection might be appropriate.

    • Declaration

      void reportPerCallStatistics(R)(auto ref R output);

      Defined if is nonzero. Outputs (e.g. to a ) a simple report of the collected per-call statistics.