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.
import std.experimental.allocator.gc_allocator : GCAllocator; import std.experimental.allocator.building_blocks.free_list : FreeList; alias Allocator = StatsCollector!(GCAllocator, Options.bytesUsed);
Options for StatsCollector
defined below. Each enables during compilation one specific counter, statistic, or other piece of information.
Counts the number of calls to owns
.
Counts the number of calls to allocate
. All calls are counted, including requests for zero bytes or failed requests.
Counts the number of calls to allocate
that succeeded, i.e. they returned a block as large as requested. (N.B. requests for zero bytes count as successful.)
Counts the number of calls to expand
, regardless of arguments or result.
Counts the number of calls to expand
that resulted in a successful expansion.
Counts the number of calls to reallocate
, regardless of arguments or result.
Counts the number of calls to reallocate
that succeeded. (Reallocations to zero bytes count as successful.)
Counts the number of calls to reallocate
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).
Counts the number of calls to deallocate
.
Counts the number of calls to deallocateAll
.
Counts the number of calls to alignedAllocate
. All calls are counted, including requests for zero bytes or failed requests.
Counts the number of calls to alignedAllocate
that succeeded, i.e. they returned a block as large as requested. (N.B. requests for zero bytes count as successful.)
Chooses all numXxx
flags.
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.
Tracks total cumulative bytes allocated by means of allocate
, expand
, and reallocate
(when resulting in an expansion). This number always grows and indicates allocation traffic. To compute bytes deallocated cumulatively, subtract bytesUsed
from bytesAllocated
.
Tracks the sum of all delta
values in calls of the form expand(b, delta)
that succeed (return true
).
Tracks the sum of all b.length - s
with b.length > s
in calls of the form realloc(b, s)
that succeed (return true
). In per-call statistics, also unambiguously counts the bytes deallocated with deallocate
.
Tracks the sum of all bytes moved as a result of calls to realloc
that were unable to reallocate in place. A large number (relative to bytesAllocated
) indicates that the application should use larger preallocations.
Tracks the sum of all bytes NOT moved as result of calls to realloc
that managed to reallocate in place. A large number (relative to bytesAllocated
) indicates that the application is expansion-intensive and is saving a good amount of moves. However, if this number is relatively small and bytesSlack
is high, it means the application is overallocating for little benefit.
Measures the sum of extra bytes allocated beyond the bytes requested, i.e. the internal fragmentation. This is the current effective number of slack bytes, and it goes up and down with time.
Measures the maximum bytes allocated over the time. This is useful for dimensioning allocators.
Chooses all byteXxx
flags.
Combines all flags above.
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 flags
.
All stats of the form numXxx
record counts of events occurring, such as calls to functions and specific results. The stats of the form bytesXxx
collect cumulative sizes.
In addition, the data callerSize
, callerModule
, callerFile
, callerLine
, and callerTime
is associated with each specific allocation. This data prefixes each allocation.
import std.experimental.allocator.building_blocks.free_list : FreeList; import std.experimental.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); import std.file : deleteme, remove; import std.range : walkLength; import std.stdio : File; auto f = deleteme ~ "-dlang.std.experimental.allocator.stats_collector.txt"; scope(exit) remove(f); Allocator.reportPerCallStatistics(File(f, "w")); alloc.reportStatistics(File(f, "a")); writeln(File(f).byLine.walkLength); // 24
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.
Alignment offered is equal to Allocator.alignment
.
Increments numOwns
(per instance and and per call) and forwards to parent.owns(b)
.
Forwards to parent.allocate
. Affects per instance: numAllocate
, bytesUsed
, bytesAllocated
, bytesSlack
, numAllocateOK
, and bytesHighTide
. Affects per call: numAllocate
, numAllocateOK
, and bytesAllocated
.
Forwards to parent.alignedAllocate
. Affects per instance: numAlignedAllocate
, bytesUsed
, bytesAllocated
, bytesSlack
, numAlignedAllocateOk
, and bytesHighTide
. Affects per call: numAlignedAllocate
, numAlignedAllocateOk
, and bytesAllocated
.
Defined whether or not Allocator.expand
is defined. Affects per instance: numExpand
, numExpandOK
, bytesExpanded
, bytesSlack
, bytesAllocated
, and bytesUsed
. Affects per call: numExpand
, numExpandOK
, bytesExpanded
, and bytesAllocated
.
Defined whether or not Allocator.reallocate
is defined. Affects per instance: numReallocate
, numReallocateOK
, numReallocateInPlace
, bytesNotMoved
, bytesAllocated
, bytesSlack
, bytesExpanded
, and bytesContracted
. Affects per call: numReallocate
, numReallocateOK
, numReallocateInPlace
, bytesNotMoved
, bytesExpanded
, bytesContracted
, and bytesMoved
.
Defined whether or not Allocator.deallocate
is defined. Affects per instance: numDeallocate
, bytesUsed
, and bytesSlack
. Affects per call: numDeallocate
and bytesContracted
.
Defined only if Allocator.deallocateAll
is defined. Affects per instance and per call numDeallocateAll
.
Defined only if Options.bytesUsed
is defined. Returns bytesUsed == 0
.
Reports per instance statistics to output
(e.g. stdout
). The format is simple: one kind and value per line, separated by a colon, e.g. bytesAllocated:7395404
Defined if perCallFlags
is nonzero.
The file and line of the call.
The options corresponding to the statistics collected.
The values of the statistics. Has the same length as opts
.
Format to a string such as: mymodule.d(655): [numAllocate:21, numAllocateOK:21, bytesAllocated:324202]
.
Defined if perCallFlags
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.
Defined if perCallFlags
is nonzero. Outputs (e.g. to a File
) a simple report of the collected per-call statistics.
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_experimental_allocator_building_blocks_stats_collector.html