2012-06-28 17:03:16 -04:00
|
|
|
/*
|
2019-02-07 14:29:17 -05:00
|
|
|
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
2012-06-28 17:03:16 -04:00
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
|
|
*
|
|
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
|
|
* accompanied this code).
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License version
|
|
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*
|
|
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
|
|
* questions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include "precompiled.hpp"
|
2014-08-07 12:18:58 -07:00
|
|
|
|
2018-09-28 16:07:39 -04:00
|
|
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
2012-06-28 17:03:16 -04:00
|
|
|
#include "memory/allocation.hpp"
|
2013-04-24 14:55:04 -04:00
|
|
|
#include "runtime/safepoint.hpp"
|
|
|
|
#include "runtime/thread.inline.hpp"
|
2012-06-28 17:03:16 -04:00
|
|
|
#include "services/memBaseline.hpp"
|
|
|
|
#include "services/memTracker.hpp"
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
/*
|
|
|
|
* Sizes are sorted in descenting order for reporting
|
|
|
|
*/
|
|
|
|
int compare_malloc_size(const MallocSite& s1, const MallocSite& s2) {
|
|
|
|
if (s1.size() == s2.size()) {
|
|
|
|
return 0;
|
|
|
|
} else if (s1.size() > s2.size()) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2013-04-24 14:55:04 -04:00
|
|
|
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
int compare_virtual_memory_size(const VirtualMemoryAllocationSite& s1,
|
|
|
|
const VirtualMemoryAllocationSite& s2) {
|
|
|
|
if (s1.reserved() == s2.reserved()) {
|
|
|
|
return 0;
|
|
|
|
} else if (s1.reserved() > s2.reserved()) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return 1;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
}
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
// Sort into allocation site addresses order for baseline comparison
|
|
|
|
int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) {
|
|
|
|
return s1.call_stack()->compare(*s2.call_stack());
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2017-07-24 15:19:46 -04:00
|
|
|
// Sort into allocation site addresses and memory type order for baseline comparison
|
|
|
|
int compare_malloc_site_and_type(const MallocSite& s1, const MallocSite& s2) {
|
|
|
|
int res = compare_malloc_site(s1, s2);
|
|
|
|
if (res == 0) {
|
2020-09-29 12:03:00 +00:00
|
|
|
res = (int)(NMTUtil::flag_to_index(s1.flag()) - NMTUtil::flag_to_index(s2.flag()));
|
2017-07-24 15:19:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1,
|
|
|
|
const VirtualMemoryAllocationSite& s2) {
|
|
|
|
return s1.call_stack()->compare(*s2.call_stack());
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Walker to walk malloc allocation site table
|
|
|
|
*/
|
|
|
|
class MallocAllocationSiteWalker : public MallocSiteWalker {
|
|
|
|
private:
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<MallocSite, compare_malloc_size> _malloc_sites;
|
2014-08-07 12:18:58 -07:00
|
|
|
size_t _count;
|
|
|
|
|
|
|
|
// Entries in MallocSiteTable with size = 0 and count = 0,
|
|
|
|
// when the malloc site is not longer there.
|
|
|
|
public:
|
2014-08-20 08:41:15 -04:00
|
|
|
MallocAllocationSiteWalker() : _count(0) { }
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
inline size_t count() const { return _count; }
|
|
|
|
|
|
|
|
LinkedList<MallocSite>* malloc_sites() {
|
|
|
|
return &_malloc_sites;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
bool do_malloc_site(const MallocSite* site) {
|
|
|
|
if (site->size() >= MemBaseline::SIZE_THRESHOLD) {
|
|
|
|
if (_malloc_sites.add(*site) != NULL) {
|
|
|
|
_count++;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false; // OOM
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// malloc site does not meet threshold, ignore and continue
|
|
|
|
return true;
|
|
|
|
}
|
2012-10-19 21:40:07 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
};
|
2012-10-19 21:40:07 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
// Compare virtual memory region's base address
|
|
|
|
int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
|
|
|
|
return r1.compare(r2);
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
// Walk all virtual memory regions for baselining
|
|
|
|
class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
|
|
|
|
private:
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base>
|
2014-08-07 12:18:58 -07:00
|
|
|
_virtual_memory_regions;
|
|
|
|
size_t _count;
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
public:
|
2014-08-20 08:41:15 -04:00
|
|
|
VirtualMemoryAllocationWalker() : _count(0) { }
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
bool do_allocation_site(const ReservedMemoryRegion* rgn) {
|
|
|
|
if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) {
|
|
|
|
if (_virtual_memory_regions.add(*rgn) != NULL) {
|
|
|
|
_count ++;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
return true;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
LinkedList<ReservedMemoryRegion>* virtual_memory_allocations() {
|
|
|
|
return &_virtual_memory_regions;
|
|
|
|
}
|
|
|
|
};
|
2012-06-28 17:03:16 -04:00
|
|
|
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
bool MemBaseline::baseline_summary() {
|
2014-08-20 08:41:15 -04:00
|
|
|
MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
|
|
|
|
VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
|
2017-09-28 09:56:54 -04:00
|
|
|
MetaspaceSnapshot::snapshot(_metaspace_snapshot);
|
2012-06-28 17:03:16 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
bool MemBaseline::baseline_allocation_sites() {
|
|
|
|
// Malloc allocation sites
|
2014-08-20 08:41:15 -04:00
|
|
|
MallocAllocationSiteWalker malloc_walker;
|
2014-08-07 12:18:58 -07:00
|
|
|
if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) {
|
|
|
|
return false;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2019-03-26 15:50:34 -04:00
|
|
|
// Walk simple thread stacks
|
|
|
|
if (!ThreadStackTracker::walk_simple_thread_stack_site(&malloc_walker)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-08-20 08:41:15 -04:00
|
|
|
_malloc_sites.move(malloc_walker.malloc_sites());
|
2014-08-07 12:18:58 -07:00
|
|
|
// The malloc sites are collected in size order
|
|
|
|
_malloc_sites_order = by_size;
|
|
|
|
|
|
|
|
// Virtual memory allocation sites
|
2014-08-20 08:41:15 -04:00
|
|
|
VirtualMemoryAllocationWalker virtual_memory_walker;
|
2014-08-07 12:18:58 -07:00
|
|
|
if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) {
|
|
|
|
return false;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
// Virtual memory allocations are collected in call stack order
|
2014-08-20 08:41:15 -04:00
|
|
|
_virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations());
|
2014-08-07 12:18:58 -07:00
|
|
|
|
|
|
|
if (!aggregate_virtual_memory_allocation_sites()) {
|
|
|
|
return false;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
// Virtual memory allocation sites are aggregrated in call stack order
|
|
|
|
_virtual_memory_sites_order = by_address;
|
|
|
|
|
2012-06-28 17:03:16 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
bool MemBaseline::baseline(bool summaryOnly) {
|
|
|
|
reset();
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2018-02-08 13:21:22 -05:00
|
|
|
_instance_class_count = ClassLoaderDataGraph::num_instance_classes();
|
|
|
|
_array_class_count = ClassLoaderDataGraph::num_array_classes();
|
2012-10-19 21:40:07 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
if (!baseline_summary()) {
|
2012-10-19 21:40:07 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
_baseline_type = Summary_baselined;
|
|
|
|
|
|
|
|
// baseline details
|
|
|
|
if (!summaryOnly &&
|
|
|
|
MemTracker::tracking_level() == NMT_detail) {
|
|
|
|
baseline_allocation_sites();
|
|
|
|
_baseline_type = Detail_baselined;
|
2012-10-19 21:40:07 -04:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:03:16 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
|
|
|
|
const VirtualMemoryAllocationSite& s2) {
|
|
|
|
return s1.call_stack()->compare(*s2.call_stack());
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites;
|
2014-08-07 12:18:58 -07:00
|
|
|
|
|
|
|
VirtualMemoryAllocationIterator itr = virtual_memory_allocations();
|
|
|
|
const ReservedMemoryRegion* rgn;
|
|
|
|
VirtualMemoryAllocationSite* site;
|
|
|
|
while ((rgn = itr.next()) != NULL) {
|
2019-02-07 14:29:17 -05:00
|
|
|
VirtualMemoryAllocationSite tmp(*rgn->call_stack(), rgn->flag());
|
2014-08-07 12:18:58 -07:00
|
|
|
site = allocation_sites.find(tmp);
|
|
|
|
if (site == NULL) {
|
|
|
|
LinkedListNode<VirtualMemoryAllocationSite>* node =
|
|
|
|
allocation_sites.add(tmp);
|
|
|
|
if (node == NULL) return false;
|
|
|
|
site = node->data();
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
site->reserve_memory(rgn->size());
|
|
|
|
site->commit_memory(rgn->committed_size());
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
|
2014-08-20 08:41:15 -04:00
|
|
|
_virtual_memory_sites.move(&allocation_sites);
|
2014-08-07 12:18:58 -07:00
|
|
|
return true;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) {
|
2014-08-20 08:41:15 -04:00
|
|
|
assert(!_malloc_sites.is_empty(), "Not detail baseline");
|
2014-08-07 12:18:58 -07:00
|
|
|
switch(order) {
|
|
|
|
case by_size:
|
|
|
|
malloc_sites_to_size_order();
|
|
|
|
break;
|
|
|
|
case by_site:
|
|
|
|
malloc_sites_to_allocation_site_order();
|
|
|
|
break;
|
2017-07-24 15:19:46 -04:00
|
|
|
case by_site_and_type:
|
|
|
|
malloc_sites_to_allocation_site_and_type_order();
|
|
|
|
break;
|
2014-08-07 12:18:58 -07:00
|
|
|
case by_address:
|
|
|
|
default:
|
|
|
|
ShouldNotReachHere();
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
return MallocSiteIterator(_malloc_sites.head());
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) {
|
2014-08-20 08:41:15 -04:00
|
|
|
assert(!_virtual_memory_sites.is_empty(), "Not detail baseline");
|
2014-08-07 12:18:58 -07:00
|
|
|
switch(order) {
|
|
|
|
case by_size:
|
|
|
|
virtual_memory_sites_to_size_order();
|
|
|
|
break;
|
|
|
|
case by_site:
|
|
|
|
virtual_memory_sites_to_reservation_site_order();
|
|
|
|
break;
|
|
|
|
case by_address:
|
|
|
|
default:
|
|
|
|
ShouldNotReachHere();
|
|
|
|
}
|
|
|
|
return VirtualMemorySiteIterator(_virtual_memory_sites.head());
|
|
|
|
}
|
2012-06-28 17:03:16 -04:00
|
|
|
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
// Sorting allocations sites in different orders
|
|
|
|
void MemBaseline::malloc_sites_to_size_order() {
|
|
|
|
if (_malloc_sites_order != by_size) {
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<MallocSite, compare_malloc_size> tmp;
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
// Add malloc sites to sorted linked list to sort into size order
|
|
|
|
tmp.move(&_malloc_sites);
|
|
|
|
_malloc_sites.set_head(tmp.head());
|
|
|
|
tmp.set_head(NULL);
|
|
|
|
_malloc_sites_order = by_size;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
2014-08-07 12:18:58 -07:00
|
|
|
}
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
void MemBaseline::malloc_sites_to_allocation_site_order() {
|
2017-07-24 15:19:46 -04:00
|
|
|
if (_malloc_sites_order != by_site && _malloc_sites_order != by_site_and_type) {
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<MallocSite, compare_malloc_site> tmp;
|
2014-08-07 12:18:58 -07:00
|
|
|
// Add malloc sites to sorted linked list to sort into site (address) order
|
|
|
|
tmp.move(&_malloc_sites);
|
|
|
|
_malloc_sites.set_head(tmp.head());
|
|
|
|
tmp.set_head(NULL);
|
|
|
|
_malloc_sites_order = by_site;
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-24 15:19:46 -04:00
|
|
|
void MemBaseline::malloc_sites_to_allocation_site_and_type_order() {
|
|
|
|
if (_malloc_sites_order != by_site_and_type) {
|
|
|
|
SortedLinkedList<MallocSite, compare_malloc_site_and_type> tmp;
|
|
|
|
// Add malloc sites to sorted linked list to sort into site (address) order
|
|
|
|
tmp.move(&_malloc_sites);
|
|
|
|
_malloc_sites.set_head(tmp.head());
|
|
|
|
tmp.set_head(NULL);
|
|
|
|
_malloc_sites_order = by_site_and_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
void MemBaseline::virtual_memory_sites_to_size_order() {
|
|
|
|
if (_virtual_memory_sites_order != by_size) {
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size> tmp;
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
tmp.move(&_virtual_memory_sites);
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
_virtual_memory_sites.set_head(tmp.head());
|
|
|
|
tmp.set_head(NULL);
|
|
|
|
_virtual_memory_sites_order = by_size;
|
|
|
|
}
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
void MemBaseline::virtual_memory_sites_to_reservation_site_order() {
|
|
|
|
if (_virtual_memory_sites_order != by_size) {
|
2014-08-20 08:41:15 -04:00
|
|
|
SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site> tmp;
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-20 08:41:15 -04:00
|
|
|
tmp.move(&_virtual_memory_sites);
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
_virtual_memory_sites.set_head(tmp.head());
|
|
|
|
tmp.set_head(NULL);
|
2012-06-28 17:03:16 -04:00
|
|
|
|
2014-08-07 12:18:58 -07:00
|
|
|
_virtual_memory_sites_order = by_size;
|
|
|
|
}
|
2012-06-28 17:03:16 -04:00
|
|
|
}
|
|
|
|
|