提交 e9741a47 编写于 作者: Z zgu

8054546: NMT2 leaks memory

Summary: Fixed memory leak in NMT by baselining memory in c heap instead of an arena.
Reviewed-by: coleenp, minqi
上级 07d26a6f
...@@ -171,8 +171,9 @@ class MallocMemorySnapshot : public ResourceObj { ...@@ -171,8 +171,9 @@ class MallocMemorySnapshot : public ResourceObj {
// Total malloc'd memory used by arenas // Total malloc'd memory used by arenas
size_t total_arena() const; size_t total_arena() const;
inline size_t thread_count() { inline size_t thread_count() const {
return by_type(mtThreadStack)->malloc_count(); MallocMemorySnapshot* s = const_cast<MallocMemorySnapshot*>(this);
return s->by_type(mtThreadStack)->malloc_count();
} }
void reset(); void reset();
......
...@@ -70,15 +70,13 @@ int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1, ...@@ -70,15 +70,13 @@ int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1,
*/ */
class MallocAllocationSiteWalker : public MallocSiteWalker { class MallocAllocationSiteWalker : public MallocSiteWalker {
private: private:
SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> SortedLinkedList<MallocSite, compare_malloc_size> _malloc_sites;
_malloc_sites;
size_t _count; size_t _count;
// Entries in MallocSiteTable with size = 0 and count = 0, // Entries in MallocSiteTable with size = 0 and count = 0,
// when the malloc site is not longer there. // when the malloc site is not longer there.
public: public:
MallocAllocationSiteWalker(Arena* arena) : _count(0), _malloc_sites(arena) { MallocAllocationSiteWalker() : _count(0) { }
}
inline size_t count() const { return _count; } inline size_t count() const { return _count; }
...@@ -109,13 +107,12 @@ int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMe ...@@ -109,13 +107,12 @@ int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMe
// Walk all virtual memory regions for baselining // Walk all virtual memory regions for baselining
class VirtualMemoryAllocationWalker : public VirtualMemoryWalker { class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
private: private:
SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base, ResourceObj::ARENA> SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base>
_virtual_memory_regions; _virtual_memory_regions;
size_t _count; size_t _count;
public: public:
VirtualMemoryAllocationWalker(Arena* a) : _count(0), _virtual_memory_regions(a) { VirtualMemoryAllocationWalker() : _count(0) { }
}
bool do_allocation_site(const ReservedMemoryRegion* rgn) { bool do_allocation_site(const ReservedMemoryRegion* rgn) {
if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) { if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) {
...@@ -136,39 +133,30 @@ class VirtualMemoryAllocationWalker : public VirtualMemoryWalker { ...@@ -136,39 +133,30 @@ class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
bool MemBaseline::baseline_summary() { bool MemBaseline::baseline_summary() {
assert(_malloc_memory_snapshot == NULL, "Malloc baseline not yet reset"); MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
assert(_virtual_memory_snapshot == NULL, "Virtual baseline not yet reset"); VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
_malloc_memory_snapshot = new (arena()) MallocMemorySnapshot();
_virtual_memory_snapshot = new (arena()) VirtualMemorySnapshot();
if (_malloc_memory_snapshot == NULL || _virtual_memory_snapshot == NULL) {
return false;
}
MallocMemorySummary::snapshot(_malloc_memory_snapshot);
VirtualMemorySummary::snapshot(_virtual_memory_snapshot);
return true; return true;
} }
bool MemBaseline::baseline_allocation_sites() { bool MemBaseline::baseline_allocation_sites() {
assert(arena() != NULL, "Just check");
// Malloc allocation sites // Malloc allocation sites
MallocAllocationSiteWalker malloc_walker(arena()); MallocAllocationSiteWalker malloc_walker;
if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) { if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) {
return false; return false;
} }
_malloc_sites.set_head(malloc_walker.malloc_sites()->head()); _malloc_sites.move(malloc_walker.malloc_sites());
// The malloc sites are collected in size order // The malloc sites are collected in size order
_malloc_sites_order = by_size; _malloc_sites_order = by_size;
// Virtual memory allocation sites // Virtual memory allocation sites
VirtualMemoryAllocationWalker virtual_memory_walker(arena()); VirtualMemoryAllocationWalker virtual_memory_walker;
if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) { if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) {
return false; return false;
} }
// Virtual memory allocations are collected in call stack order // Virtual memory allocations are collected in call stack order
_virtual_memory_allocations.set_head(virtual_memory_walker.virtual_memory_allocations()->head()); _virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations());
if (!aggregate_virtual_memory_allocation_sites()) { if (!aggregate_virtual_memory_allocation_sites()) {
return false; return false;
...@@ -180,11 +168,6 @@ bool MemBaseline::baseline_allocation_sites() { ...@@ -180,11 +168,6 @@ bool MemBaseline::baseline_allocation_sites() {
} }
bool MemBaseline::baseline(bool summaryOnly) { bool MemBaseline::baseline(bool summaryOnly) {
if (arena() == NULL) {
_arena = new (std::nothrow, mtNMT) Arena(mtNMT);
if (arena() == NULL) return false;
}
reset(); reset();
_class_count = InstanceKlass::number_of_instance_classes(); _class_count = InstanceKlass::number_of_instance_classes();
...@@ -211,8 +194,7 @@ int compare_allocation_site(const VirtualMemoryAllocationSite& s1, ...@@ -211,8 +194,7 @@ int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
} }
bool MemBaseline::aggregate_virtual_memory_allocation_sites() { bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site, ResourceObj::ARENA> SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites;
allocation_sites(arena());
VirtualMemoryAllocationIterator itr = virtual_memory_allocations(); VirtualMemoryAllocationIterator itr = virtual_memory_allocations();
const ReservedMemoryRegion* rgn; const ReservedMemoryRegion* rgn;
...@@ -230,12 +212,12 @@ bool MemBaseline::aggregate_virtual_memory_allocation_sites() { ...@@ -230,12 +212,12 @@ bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
site->commit_memory(rgn->committed_size()); site->commit_memory(rgn->committed_size());
} }
_virtual_memory_sites.set_head(allocation_sites.head()); _virtual_memory_sites.move(&allocation_sites);
return true; return true;
} }
MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) { MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) {
assert(!_malloc_sites.is_empty(), "Detail baseline?"); assert(!_malloc_sites.is_empty(), "Not detail baseline");
switch(order) { switch(order) {
case by_size: case by_size:
malloc_sites_to_size_order(); malloc_sites_to_size_order();
...@@ -251,7 +233,7 @@ MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) { ...@@ -251,7 +233,7 @@ MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) {
} }
VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) { VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) {
assert(!_virtual_memory_sites.is_empty(), "Detail baseline?"); assert(!_virtual_memory_sites.is_empty(), "Not detail baseline");
switch(order) { switch(order) {
case by_size: case by_size:
virtual_memory_sites_to_size_order(); virtual_memory_sites_to_size_order();
...@@ -270,8 +252,7 @@ VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) ...@@ -270,8 +252,7 @@ VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order)
// Sorting allocations sites in different orders // Sorting allocations sites in different orders
void MemBaseline::malloc_sites_to_size_order() { void MemBaseline::malloc_sites_to_size_order() {
if (_malloc_sites_order != by_size) { if (_malloc_sites_order != by_size) {
SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> SortedLinkedList<MallocSite, compare_malloc_size> tmp;
tmp(arena());
// Add malloc sites to sorted linked list to sort into size order // Add malloc sites to sorted linked list to sort into size order
tmp.move(&_malloc_sites); tmp.move(&_malloc_sites);
...@@ -283,8 +264,7 @@ void MemBaseline::malloc_sites_to_size_order() { ...@@ -283,8 +264,7 @@ void MemBaseline::malloc_sites_to_size_order() {
void MemBaseline::malloc_sites_to_allocation_site_order() { void MemBaseline::malloc_sites_to_allocation_site_order() {
if (_malloc_sites_order != by_site) { if (_malloc_sites_order != by_site) {
SortedLinkedList<MallocSite, compare_malloc_site, ResourceObj::ARENA> SortedLinkedList<MallocSite, compare_malloc_site> tmp;
tmp(arena());
// Add malloc sites to sorted linked list to sort into site (address) order // Add malloc sites to sorted linked list to sort into site (address) order
tmp.move(&_malloc_sites); tmp.move(&_malloc_sites);
_malloc_sites.set_head(tmp.head()); _malloc_sites.set_head(tmp.head());
...@@ -295,8 +275,7 @@ void MemBaseline::malloc_sites_to_allocation_site_order() { ...@@ -295,8 +275,7 @@ void MemBaseline::malloc_sites_to_allocation_site_order() {
void MemBaseline::virtual_memory_sites_to_size_order() { void MemBaseline::virtual_memory_sites_to_size_order() {
if (_virtual_memory_sites_order != by_size) { if (_virtual_memory_sites_order != by_size) {
SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size, ResourceObj::ARENA> SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size> tmp;
tmp(arena());
tmp.move(&_virtual_memory_sites); tmp.move(&_virtual_memory_sites);
...@@ -308,10 +287,9 @@ void MemBaseline::virtual_memory_sites_to_size_order() { ...@@ -308,10 +287,9 @@ void MemBaseline::virtual_memory_sites_to_size_order() {
void MemBaseline::virtual_memory_sites_to_reservation_site_order() { void MemBaseline::virtual_memory_sites_to_reservation_site_order() {
if (_virtual_memory_sites_order != by_size) { if (_virtual_memory_sites_order != by_size) {
SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site, ResourceObj::ARENA> SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site> tmp;
tmp(arena());
tmp.add(&_virtual_memory_sites); tmp.move(&_virtual_memory_sites);
_virtual_memory_sites.set_head(tmp.head()); _virtual_memory_sites.set_head(tmp.head());
tmp.set_head(NULL); tmp.set_head(NULL);
......
...@@ -61,28 +61,22 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC { ...@@ -61,28 +61,22 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC {
}; };
private: private:
// All baseline data is stored in this arena
Arena* _arena;
// Summary information // Summary information
MallocMemorySnapshot* _malloc_memory_snapshot; MallocMemorySnapshot _malloc_memory_snapshot;
VirtualMemorySnapshot* _virtual_memory_snapshot; VirtualMemorySnapshot _virtual_memory_snapshot;
size_t _class_count; size_t _class_count;
// Allocation sites information // Allocation sites information
// Malloc allocation sites // Malloc allocation sites
LinkedListImpl<MallocSite, ResourceObj::ARENA> LinkedListImpl<MallocSite> _malloc_sites;
_malloc_sites;
// All virtual memory allocations // All virtual memory allocations
LinkedListImpl<ReservedMemoryRegion, ResourceObj::ARENA> LinkedListImpl<ReservedMemoryRegion> _virtual_memory_allocations;
_virtual_memory_allocations;
// Virtual memory allocations by allocation sites, always in by_address // Virtual memory allocations by allocation sites, always in by_address
// order // order
LinkedListImpl<VirtualMemoryAllocationSite, ResourceObj::ARENA> LinkedListImpl<VirtualMemoryAllocationSite> _virtual_memory_sites;
_virtual_memory_sites;
SortingOrder _malloc_sites_order; SortingOrder _malloc_sites_order;
SortingOrder _virtual_memory_sites_order; SortingOrder _virtual_memory_sites_order;
...@@ -93,30 +87,23 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC { ...@@ -93,30 +87,23 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC {
// create a memory baseline // create a memory baseline
MemBaseline(): MemBaseline():
_baseline_type(Not_baselined), _baseline_type(Not_baselined),
_class_count(0), _class_count(0) {
_arena(NULL),
_malloc_memory_snapshot(NULL),
_virtual_memory_snapshot(NULL),
_malloc_sites(NULL) {
} }
~MemBaseline() { ~MemBaseline() {
reset(); reset();
if (_arena != NULL) {
delete _arena;
}
} }
bool baseline(bool summaryOnly = true); bool baseline(bool summaryOnly = true);
BaselineType baseline_type() const { return _baseline_type; } BaselineType baseline_type() const { return _baseline_type; }
MallocMemorySnapshot* malloc_memory_snapshot() const { MallocMemorySnapshot* malloc_memory_snapshot() {
return _malloc_memory_snapshot; return &_malloc_memory_snapshot;
} }
VirtualMemorySnapshot* virtual_memory_snapshot() const { VirtualMemorySnapshot* virtual_memory_snapshot() {
return _virtual_memory_snapshot; return &_virtual_memory_snapshot;
} }
MallocSiteIterator malloc_sites(SortingOrder order); MallocSiteIterator malloc_sites(SortingOrder order);
...@@ -133,10 +120,8 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC { ...@@ -133,10 +120,8 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC {
// memory // memory
size_t total_reserved_memory() const { size_t total_reserved_memory() const {
assert(baseline_type() != Not_baselined, "Not yet baselined"); assert(baseline_type() != Not_baselined, "Not yet baselined");
assert(_virtual_memory_snapshot != NULL, "No virtual memory snapshot"); size_t amount = _malloc_memory_snapshot.total() +
assert(_malloc_memory_snapshot != NULL, "No malloc memory snapshot"); _virtual_memory_snapshot.total_reserved();
size_t amount = _malloc_memory_snapshot->total() +
_virtual_memory_snapshot->total_reserved();
return amount; return amount;
} }
...@@ -144,32 +129,30 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC { ...@@ -144,32 +129,30 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC {
// virtual memory // virtual memory
size_t total_committed_memory() const { size_t total_committed_memory() const {
assert(baseline_type() != Not_baselined, "Not yet baselined"); assert(baseline_type() != Not_baselined, "Not yet baselined");
assert(_virtual_memory_snapshot != NULL, size_t amount = _malloc_memory_snapshot.total() +
"Not a snapshot"); _virtual_memory_snapshot.total_committed();
size_t amount = _malloc_memory_snapshot->total() +
_virtual_memory_snapshot->total_committed();
return amount; return amount;
} }
size_t total_arena_memory() const { size_t total_arena_memory() const {
assert(baseline_type() != Not_baselined, "Not yet baselined"); assert(baseline_type() != Not_baselined, "Not yet baselined");
assert(_malloc_memory_snapshot != NULL, "Not yet baselined"); return _malloc_memory_snapshot.total_arena();
return _malloc_memory_snapshot->total_arena();
} }
size_t malloc_tracking_overhead() const { size_t malloc_tracking_overhead() const {
assert(baseline_type() != Not_baselined, "Not yet baselined"); assert(baseline_type() != Not_baselined, "Not yet baselined");
return _malloc_memory_snapshot->malloc_overhead()->size(); MemBaseline* bl = const_cast<MemBaseline*>(this);
return bl->_malloc_memory_snapshot.malloc_overhead()->size();
} }
const MallocMemory* malloc_memory(MEMFLAGS flag) const { MallocMemory* malloc_memory(MEMFLAGS flag) {
assert(_malloc_memory_snapshot != NULL, "Not a snapshot"); assert(baseline_type() != Not_baselined, "Not yet baselined");
return _malloc_memory_snapshot->by_type(flag); return _malloc_memory_snapshot.by_type(flag);
} }
const VirtualMemory* virtual_memory(MEMFLAGS flag) const { VirtualMemory* virtual_memory(MEMFLAGS flag) {
assert(_virtual_memory_snapshot != NULL, "Not a snapshot"); assert(baseline_type() != Not_baselined, "Not yet baselined");
return _virtual_memory_snapshot->by_type(flag); return _virtual_memory_snapshot.by_type(flag);
} }
...@@ -180,24 +163,19 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC { ...@@ -180,24 +163,19 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC {
size_t thread_count() const { size_t thread_count() const {
assert(baseline_type() != Not_baselined, "Not yet baselined"); assert(baseline_type() != Not_baselined, "Not yet baselined");
assert(_malloc_memory_snapshot != NULL, "Baselined?"); return _malloc_memory_snapshot.thread_count();
return _malloc_memory_snapshot->thread_count();
} }
// reset the baseline for reuse // reset the baseline for reuse
void reset() { void reset() {
_baseline_type = Not_baselined; _baseline_type = Not_baselined;
_malloc_memory_snapshot = NULL; _malloc_memory_snapshot.reset();
_virtual_memory_snapshot = NULL; _virtual_memory_snapshot.reset();
_class_count = 0; _class_count = 0;
_malloc_sites = NULL; _malloc_sites.clear();
_virtual_memory_sites = NULL; _virtual_memory_sites.clear();
_virtual_memory_allocations = NULL; _virtual_memory_allocations.clear();
if (_arena != NULL) {
_arena->destruct_contents();
}
} }
private: private:
...@@ -210,8 +188,6 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC { ...@@ -210,8 +188,6 @@ class MemBaseline VALUE_OBJ_CLASS_SPEC {
// Aggregate virtual memory allocation by allocation sites // Aggregate virtual memory allocation by allocation sites
bool aggregate_virtual_memory_allocation_sites(); bool aggregate_virtual_memory_allocation_sites();
Arena* arena() { return _arena; }
// Sorting allocation sites in different orders // Sorting allocation sites in different orders
// Sort allocation sites in size order // Sort allocation sites in size order
void malloc_sites_to_size_order(); void malloc_sites_to_size_order();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册