Added simple stats tracking memory usage (#241)

These statistics can be maintained with effectively zero cost to
realistic applications.  They do not track the precise amount of
memory used, but are an over-approximation.
This commit is contained in:
Matthew Parkinson
2020-08-28 14:01:52 +01:00
committed by GitHub
parent 234c0e2e8e
commit 77ebff6909
4 changed files with 180 additions and 5 deletions

View File

@@ -70,7 +70,17 @@ namespace snmalloc
*/
AddressSpaceManager<PAL> address_space = {};
/**
* High-water mark of used memory.
*/
std::atomic<size_t> peak_memory_used_bytes{0};
public:
/**
* Memory current available in large_stacks
*/
std::atomic<size_t> available_large_chunks_in_bytes{0};
/**
* Stack of large allocations that have been returned for reuse.
*/
@@ -184,10 +194,13 @@ namespace snmalloc
{
// Cache line align
size_t size = bits::align_up(sizeof(T), 64);
size = bits::max(size, alignment);
void* p = address_space.template reserve<true>(bits::next_pow2(size));
size = bits::next_pow2(bits::max(size, alignment));
void* p = address_space.template reserve<true>(size);
if (p == nullptr)
return nullptr;
peak_memory_used_bytes += size;
return new (p) T(std::forward<Args...>(args)...);
}
@@ -195,9 +208,20 @@ namespace snmalloc
void* reserve(size_t large_class) noexcept
{
size_t size = bits::one_at_bit(SUPERSLAB_BITS) << large_class;
peak_memory_used_bytes += size;
return address_space.template reserve<committed>(size);
}
/**
* Returns a pair of current memory usage and peak memory usage.
* Both statistics are very coarse-grained.
*/
std::pair<size_t, size_t> memory_usage()
{
size_t avail = available_large_chunks_in_bytes;
size_t peak = peak_memory_used_bytes;
return {peak - avail, peak};
}
};
using Stats = AllocStats<NUM_SIZECLASSES, NUM_LARGE_CLASSES>;
@@ -239,6 +263,7 @@ namespace snmalloc
else
{
stats.superslab_pop();
memory_provider.available_large_chunks_in_bytes -= rsize;
// Cross-reference alloc.h's large_dealloc decommitment condition.
bool decommitted =
@@ -284,18 +309,19 @@ namespace snmalloc
"without low memory notifications");
}
size_t rsize = bits::one_at_bit(SUPERSLAB_BITS) << large_class;
// Cross-reference largealloc's alloc() decommitted condition.
if (
(decommit_strategy != DecommitNone) &&
(large_class != 0 || decommit_strategy == DecommitSuper))
{
size_t rsize = bits::one_at_bit(SUPERSLAB_BITS) << large_class;
memory_provider.notify_not_using(
pointer_offset(p, OS_PAGE_SIZE), rsize - OS_PAGE_SIZE);
}
stats.superslab_push();
memory_provider.available_large_chunks_in_bytes += rsize;
memory_provider.large_stack[large_class].push(static_cast<Largeslab*>(p));
}
};