mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8139673: NMT stack traces in output should show mtcomponent
Show memory types of malloc site in detail report Co-authored-by: Max Ockner <max.ockner@oracle.com> Reviewed-by: dholmes, shade, coleenp
This commit is contained in:
parent
0ee4f3019d
commit
fd9c3d8158
6 changed files with 46 additions and 31 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -97,7 +97,7 @@ bool MallocSiteTable::initialize() {
|
|||
|
||||
// Instantiate hash entry for hashtable entry allocation callsite
|
||||
MallocSiteHashtableEntry* entry = ::new ((void*)_hash_entry_allocation_site)
|
||||
MallocSiteHashtableEntry(*stack);
|
||||
MallocSiteHashtableEntry(*stack, mtNMT);
|
||||
|
||||
// Add the allocation site to hashtable.
|
||||
int index = hash_to_index(stack->hash());
|
||||
|
@ -134,14 +134,15 @@ bool MallocSiteTable::walk(MallocSiteWalker* walker) {
|
|||
* Under any of above circumstances, caller should handle the situation.
|
||||
*/
|
||||
MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx,
|
||||
size_t* pos_idx) {
|
||||
size_t* pos_idx, MEMFLAGS flags) {
|
||||
assert(flags != mtNone, "Should have a real memory type");
|
||||
unsigned int index = hash_to_index(key.hash());
|
||||
*bucket_idx = (size_t)index;
|
||||
*pos_idx = 0;
|
||||
|
||||
// First entry for this hash bucket
|
||||
if (_table[index] == NULL) {
|
||||
MallocSiteHashtableEntry* entry = new_entry(key);
|
||||
MallocSiteHashtableEntry* entry = new_entry(key, flags);
|
||||
// OOM check
|
||||
if (entry == NULL) return NULL;
|
||||
|
||||
|
@ -156,13 +157,12 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* b
|
|||
MallocSiteHashtableEntry* head = _table[index];
|
||||
while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) {
|
||||
MallocSite* site = head->data();
|
||||
if (site->equals(key)) {
|
||||
// found matched entry
|
||||
if (site->flags() == flags && site->equals(key)) {
|
||||
return head->data();
|
||||
}
|
||||
|
||||
if (head->next() == NULL && (*pos_idx) < MAX_BUCKET_LENGTH) {
|
||||
MallocSiteHashtableEntry* entry = new_entry(key);
|
||||
MallocSiteHashtableEntry* entry = new_entry(key, flags);
|
||||
// OOM check
|
||||
if (entry == NULL) return NULL;
|
||||
if (head->atomic_insert(entry)) {
|
||||
|
@ -191,10 +191,10 @@ MallocSite* MallocSiteTable::malloc_site(size_t bucket_idx, size_t pos_idx) {
|
|||
// Allocates MallocSiteHashtableEntry object. Special call stack
|
||||
// (pre-installed allocation site) has to be used to avoid infinite
|
||||
// recursion.
|
||||
MallocSiteHashtableEntry* MallocSiteTable::new_entry(const NativeCallStack& key) {
|
||||
MallocSiteHashtableEntry* MallocSiteTable::new_entry(const NativeCallStack& key, MEMFLAGS flags) {
|
||||
void* p = AllocateHeap(sizeof(MallocSiteHashtableEntry), mtNMT,
|
||||
*hash_entry_allocation_stack(), AllocFailStrategy::RETURN_NULL);
|
||||
return ::new (p) MallocSiteHashtableEntry(key);
|
||||
return ::new (p) MallocSiteHashtableEntry(key, flags);
|
||||
}
|
||||
|
||||
void MallocSiteTable::reset() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -37,12 +37,16 @@
|
|||
// MallocSite represents a code path that eventually calls
|
||||
// os::malloc() to allocate memory
|
||||
class MallocSite : public AllocationSite<MemoryCounter> {
|
||||
private:
|
||||
MEMFLAGS _flags;
|
||||
|
||||
public:
|
||||
MallocSite() :
|
||||
AllocationSite<MemoryCounter>(NativeCallStack::EMPTY_STACK) { }
|
||||
AllocationSite<MemoryCounter>(NativeCallStack::EMPTY_STACK), _flags(mtNone) {}
|
||||
|
||||
MallocSite(const NativeCallStack& stack, MEMFLAGS flags) :
|
||||
AllocationSite<MemoryCounter>(stack), _flags(flags) {}
|
||||
|
||||
MallocSite(const NativeCallStack& stack) :
|
||||
AllocationSite<MemoryCounter>(stack) { }
|
||||
|
||||
void allocate(size_t size) { data()->allocate(size); }
|
||||
void deallocate(size_t size) { data()->deallocate(size); }
|
||||
|
@ -51,6 +55,7 @@ class MallocSite : public AllocationSite<MemoryCounter> {
|
|||
size_t size() const { return peek()->size(); }
|
||||
// The number of calls were made
|
||||
size_t count() const { return peek()->count(); }
|
||||
MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
|
||||
};
|
||||
|
||||
// Malloc site hashtable entry
|
||||
|
@ -62,8 +67,10 @@ class MallocSiteHashtableEntry : public CHeapObj<mtNMT> {
|
|||
public:
|
||||
MallocSiteHashtableEntry() : _next(NULL) { }
|
||||
|
||||
MallocSiteHashtableEntry(const NativeCallStack& stack):
|
||||
_malloc_site(stack), _next(NULL) { }
|
||||
MallocSiteHashtableEntry(NativeCallStack stack, MEMFLAGS flags):
|
||||
_malloc_site(stack, flags), _next(NULL) {
|
||||
assert(flags != mtNone, "Expect a real memory type");
|
||||
}
|
||||
|
||||
inline const MallocSiteHashtableEntry* next() const {
|
||||
return _next;
|
||||
|
@ -198,11 +205,11 @@ class MallocSiteTable : AllStatic {
|
|||
// 1. out of memory
|
||||
// 2. overflow hash bucket
|
||||
static inline bool allocation_at(const NativeCallStack& stack, size_t size,
|
||||
size_t* bucket_idx, size_t* pos_idx) {
|
||||
size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) {
|
||||
AccessLock locker(&_access_count);
|
||||
if (locker.sharedLock()) {
|
||||
NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);)
|
||||
MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx);
|
||||
MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx, flags);
|
||||
if (site != NULL) site->allocate(size);
|
||||
return site != NULL;
|
||||
}
|
||||
|
@ -228,13 +235,13 @@ class MallocSiteTable : AllStatic {
|
|||
static bool walk_malloc_site(MallocSiteWalker* walker);
|
||||
|
||||
private:
|
||||
static MallocSiteHashtableEntry* new_entry(const NativeCallStack& key);
|
||||
static MallocSiteHashtableEntry* new_entry(const NativeCallStack& key, MEMFLAGS flags);
|
||||
static void reset();
|
||||
|
||||
// Delete a bucket linked list
|
||||
static void delete_linked_list(MallocSiteHashtableEntry* head);
|
||||
|
||||
static MallocSite* lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx);
|
||||
static MallocSite* lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags);
|
||||
static MallocSite* malloc_site(size_t bucket_idx, size_t pos_idx);
|
||||
static bool walk(MallocSiteWalker* walker);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -77,8 +77,8 @@ void MallocHeader::release() const {
|
|||
}
|
||||
|
||||
bool MallocHeader::record_malloc_site(const NativeCallStack& stack, size_t size,
|
||||
size_t* bucket_idx, size_t* pos_idx) const {
|
||||
bool ret = MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx);
|
||||
size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) const {
|
||||
bool ret = MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx, flags);
|
||||
|
||||
// Something went wrong, could be OOM or overflow malloc site table.
|
||||
// We want to keep tracking data under OOM circumstance, so transition to
|
||||
|
|
|
@ -275,7 +275,7 @@ class MallocHeader VALUE_OBJ_CLASS_SPEC {
|
|||
if (level == NMT_detail) {
|
||||
size_t bucket_idx;
|
||||
size_t pos_idx;
|
||||
if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) {
|
||||
if (record_malloc_site(stack, size, &bucket_idx, &pos_idx, flags)) {
|
||||
assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index");
|
||||
assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index");
|
||||
_bucket_idx = bucket_idx;
|
||||
|
@ -299,7 +299,7 @@ class MallocHeader VALUE_OBJ_CLASS_SPEC {
|
|||
_size = size;
|
||||
}
|
||||
bool record_malloc_site(const NativeCallStack& stack, size_t size,
|
||||
size_t* bucket_idx, size_t* pos_idx) const;
|
||||
size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -43,11 +43,16 @@ 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) const {
|
||||
void MemReporterBase::print_malloc(size_t amount, size_t count, MEMFLAGS flag) const {
|
||||
const char* scale = current_scale();
|
||||
outputStream* out = output();
|
||||
if (flag != mtNone) {
|
||||
out->print("(malloc=" SIZE_FORMAT "%s type=%s",
|
||||
amount_in_current_scale(amount), scale, NMTUtil::flag_to_name(flag));
|
||||
} else {
|
||||
out->print("(malloc=" SIZE_FORMAT "%s",
|
||||
amount_in_current_scale(amount), scale);
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
out->print(" #" SIZE_FORMAT "", count);
|
||||
|
@ -200,7 +205,10 @@ void MemDetailReporter::report_malloc_sites() {
|
|||
const NativeCallStack* stack = malloc_site->call_stack();
|
||||
stack->print_on(out);
|
||||
out->print("%29s", " ");
|
||||
print_malloc(malloc_site->size(), malloc_site->count());
|
||||
MEMFLAGS flag = malloc_site->flags();
|
||||
assert((flag >= 0 && flag < (int)mt_number_of_types) && flag != mtNone,
|
||||
"Must have a valid memory type");
|
||||
print_malloc(malloc_site->size(), malloc_site->count(),flag);
|
||||
out->print_cr("\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -76,7 +76,7 @@ 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) const;
|
||||
void print_malloc(size_t amount, size_t count, 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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue