8297958: NMT: Display peak values

Reviewed-by: jsjolen, sjohanss
This commit is contained in:
Thomas Stuefe 2022-12-06 18:32:42 +00:00
parent 0d2a9ee528
commit 336d230a39
5 changed files with 81 additions and 57 deletions

View File

@ -46,8 +46,12 @@ class MallocSite : public AllocationSite {
// Memory allocated from this code path
size_t size() const { return _c.size(); }
// Peak memory ever allocated from this code path
size_t peak_size() const { return _c.peak_size(); }
// The number of calls were made
size_t count() const { return _c.count(); }
const MemoryCounter* counter() const { return &_c; }
};
// Malloc site hashtable entry

View File

@ -27,6 +27,7 @@
#include "jvm_io.h"
#include "logging/log.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.hpp"
#include "services/mallocHeader.inline.hpp"
@ -42,34 +43,20 @@ size_t MallocMemorySummary::_limits_per_category[mt_number_of_types] = { 0 };
size_t MallocMemorySummary::_total_limit = 0;
#ifdef ASSERT
void MemoryCounter::update_peak_count(size_t count) {
size_t peak_cnt = peak_count();
while (peak_cnt < count) {
size_t old_cnt = Atomic::cmpxchg(&_peak_count, peak_cnt, count, memory_order_relaxed);
if (old_cnt != peak_cnt) {
peak_cnt = old_cnt;
}
}
}
void MemoryCounter::update_peak_size(size_t sz) {
void MemoryCounter::update_peak(size_t size, size_t cnt) {
size_t peak_sz = peak_size();
while (peak_sz < sz) {
size_t old_sz = Atomic::cmpxchg(&_peak_size, peak_sz, sz, memory_order_relaxed);
if (old_sz != peak_sz) {
while (peak_sz < size) {
size_t old_sz = Atomic::cmpxchg(&_peak_size, peak_sz, size, memory_order_relaxed);
if (old_sz == peak_sz) {
// I won
_peak_count = cnt;
break;
} else {
peak_sz = old_sz;
}
}
}
size_t MemoryCounter::peak_count() const {
return Atomic::load(&_peak_count);
}
size_t MemoryCounter::peak_size() const {
return Atomic::load(&_peak_size);
}
#endif
#endif // ASSERT
// Total malloc'd memory used by arenas
size_t MallocMemorySnapshot::total_arena() const {

View File

@ -45,8 +45,13 @@ class MemoryCounter {
volatile size_t _count;
volatile size_t _size;
DEBUG_ONLY(volatile size_t _peak_count;)
DEBUG_ONLY(volatile size_t _peak_size; )
#ifdef ASSERT
// Peak size and count. Note: Peak count is the count at the point
// peak size was reached, not the absolute highest peak count.
volatile size_t _peak_count;
volatile size_t _peak_size;
void update_peak(size_t size, size_t cnt);
#endif // ASSERT
public:
MemoryCounter() : _count(0), _size(0) {
@ -58,9 +63,8 @@ class MemoryCounter {
size_t cnt = Atomic::add(&_count, size_t(1), memory_order_relaxed);
if (sz > 0) {
size_t sum = Atomic::add(&_size, sz, memory_order_relaxed);
DEBUG_ONLY(update_peak_size(sum);)
DEBUG_ONLY(update_peak(sum, cnt);)
}
DEBUG_ONLY(update_peak_count(cnt);)
}
inline void deallocate(size_t sz) {
@ -76,19 +80,20 @@ class MemoryCounter {
if (sz != 0) {
assert(sz >= 0 || size() >= size_t(-sz), "Must be");
size_t sum = Atomic::add(&_size, size_t(sz), memory_order_relaxed);
DEBUG_ONLY(update_peak_size(sum);)
DEBUG_ONLY(update_peak(sum, _count);)
}
}
inline size_t count() const { return Atomic::load(&_count); }
inline size_t size() const { return Atomic::load(&_size); }
#ifdef ASSERT
void update_peak_count(size_t cnt);
void update_peak_size(size_t sz);
size_t peak_count() const;
size_t peak_size() const;
#endif // ASSERT
inline size_t peak_count() const {
return DEBUG_ONLY(Atomic::load(&_peak_count)) NOT_DEBUG(0);
}
inline size_t peak_size() const {
return DEBUG_ONLY(Atomic::load(&_peak_size)) NOT_DEBUG(0);
}
};
/*
@ -125,12 +130,14 @@ class MallocMemory {
}
inline size_t malloc_size() const { return _malloc.size(); }
inline size_t malloc_peak_size() const { return _malloc.peak_size(); }
inline size_t malloc_count() const { return _malloc.count();}
inline size_t arena_size() const { return _arena.size(); }
inline size_t arena_peak_size() const { return _arena.peak_size(); }
inline size_t arena_count() const { return _arena.count(); }
DEBUG_ONLY(inline const MemoryCounter& malloc_counter() const { return _malloc; })
DEBUG_ONLY(inline const MemoryCounter& arena_counter() const { return _arena; })
const MemoryCounter* malloc_counter() const { return &_malloc; }
const MemoryCounter* arena_counter() const { return &_arena; }
};
class MallocMemorySummary;

View File

@ -45,11 +45,14 @@ void MemReporterBase::print_total(size_t reserved, size_t committed) const {
amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
}
void MemReporterBase::print_malloc(size_t amount, size_t count, MEMFLAGS flag) const {
void MemReporterBase::print_malloc(const MemoryCounter* c, MEMFLAGS flag) const {
const char* scale = current_scale();
outputStream* out = output();
const char* alloc_type = (flag == mtThreadStack) ? "" : "malloc=";
const size_t amount = c->size();
const size_t count = c->count();
if (flag != mtNone) {
out->print("(%s" SIZE_FORMAT "%s type=%s", alloc_type,
amount_in_current_scale(amount), scale, NMTUtil::flag_to_name(flag));
@ -58,11 +61,21 @@ void MemReporterBase::print_malloc(size_t amount, size_t count, MEMFLAGS flag) c
amount_in_current_scale(amount), scale);
}
// blends out mtChunk count number
if (count > 0) {
out->print(" #" SIZE_FORMAT "", count);
}
out->print(")");
size_t pk_amount = c->peak_size();
if (pk_amount == amount) {
out->print_raw(" (at peak)");
} else if (pk_amount > amount) {
size_t pk_count = c->peak_count();
out->print(" (peak=" SIZE_FORMAT "%s #" SIZE_FORMAT ")",
amount_in_current_scale(pk_amount), scale, pk_count);
}
}
void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) const {
@ -71,9 +84,9 @@ void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) co
amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
}
void MemReporterBase::print_malloc_line(size_t amount, size_t count) const {
void MemReporterBase::print_malloc_line(const MemoryCounter* c) const {
output()->print("%28s", " ");
print_malloc(amount, count);
print_malloc(c);
output()->print_cr(" ");
}
@ -83,10 +96,26 @@ void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committe
output()->print_cr(" ");
}
void MemReporterBase::print_arena_line(size_t amount, size_t count) const {
void MemReporterBase::print_arena_line(const MemoryCounter* c) const {
const char* scale = current_scale();
output()->print_cr("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", " ",
outputStream* out = output();
const size_t amount = c->size();
const size_t count = c->count();
out->print("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", "",
amount_in_current_scale(amount), scale, count);
size_t pk_amount = c->peak_size();
if (pk_amount == amount) {
out->print_raw(" (at peak)");
} else if (pk_amount > amount) {
size_t pk_count = c->peak_count();
out->print(" (peak=" SIZE_FORMAT "%s #" SIZE_FORMAT ")",
amount_in_current_scale(pk_amount), scale, pk_count);
}
out->cr();
}
void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const {
@ -195,18 +224,18 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag,
}
// report malloc'd memory
if (amount_in_current_scale(malloc_memory->malloc_size()) > 0) {
// We don't know how many arena chunks are in used, so don't report the count
size_t count = (flag == mtChunk) ? 0 : malloc_memory->malloc_count();
print_malloc_line(malloc_memory->malloc_size(), count);
if (amount_in_current_scale(malloc_memory->malloc_size()) > 0
DEBUG_ONLY(|| amount_in_current_scale(malloc_memory->malloc_peak_size()) > 0)) {
print_malloc_line(malloc_memory->malloc_counter());
}
if (amount_in_current_scale(virtual_memory->reserved()) > 0) {
print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed());
}
if (amount_in_current_scale(malloc_memory->arena_size()) > 0) {
print_arena_line(malloc_memory->arena_size(), malloc_memory->arena_count());
if (amount_in_current_scale(malloc_memory->arena_size()) > 0
DEBUG_ONLY(|| amount_in_current_scale(malloc_memory->arena_peak_size()) > 0)) {
print_arena_line(malloc_memory->arena_counter());
}
if (flag == mtNMT &&
@ -271,12 +300,9 @@ int MemDetailReporter::report_malloc_sites() {
const MallocSite* malloc_site;
int num_omitted = 0;
while ((malloc_site = malloc_itr.next()) != NULL) {
// Don't report free sites; does not count toward omitted count.
if (malloc_site->size() == 0) {
continue;
}
// Don't report if site has allocated less than one unit of whatever our scale is
if (scale() > 1 && amount_in_current_scale(malloc_site->size()) == 0) {
// Don't report if site has never allocated less than one unit of whatever our scale is
if (scale() > 1 && amount_in_current_scale(malloc_site->size()) == 0
DEBUG_ONLY(&& amount_in_current_scale(malloc_site->peak_size()) == 0)) {
num_omitted ++;
continue;
}
@ -286,7 +312,7 @@ int MemDetailReporter::report_malloc_sites() {
MEMFLAGS flag = malloc_site->flag();
assert(NMTUtil::flag_is_valid(flag) && flag != mtNone,
"Must have a valid memory type");
print_malloc(malloc_site->size(), malloc_site->count(),flag);
print_malloc(malloc_site->counter(), flag);
out->print_cr("\n");
}
return num_omitted;

View File

@ -80,12 +80,12 @@ class MemReporterBase : public StackObj {
// Print summary total, malloc and virtual memory
void print_total(size_t reserved, size_t committed) const;
void print_malloc(size_t amount, size_t count, MEMFLAGS flag = mtNone) const;
void print_malloc(const MemoryCounter* c, MEMFLAGS flag = mtNone) const;
void print_virtual_memory(size_t reserved, size_t committed) const;
void print_malloc_line(size_t amount, size_t count) const;
void print_malloc_line(const MemoryCounter* c) const;
void print_virtual_memory_line(size_t reserved, size_t committed) const;
void print_arena_line(size_t amount, size_t count) const;
void print_arena_line(const MemoryCounter* c) const;
void print_virtual_memory_region(const char* type, address base, size_t size) const;
};