8251392: Consolidate Metaspace Statistics

Reviewed-by: coleenp, zgu
This commit is contained in:
Thomas Stuefe 2021-05-18 06:35:17 +00:00
parent 3e97b07a68
commit 554caf33a0
33 changed files with 289 additions and 400 deletions

View File

@ -331,9 +331,10 @@ void EpsilonHeap::print_heap_info(size_t used) const {
}
void EpsilonHeap::print_metaspace_info() const {
size_t reserved = MetaspaceUtils::reserved_bytes();
size_t committed = MetaspaceUtils::committed_bytes();
size_t used = MetaspaceUtils::used_bytes();
MetaspaceCombinedStats stats = MetaspaceUtils::get_combined_statistics();
size_t reserved = stats.reserved();
size_t committed = stats.committed();
size_t used = stats.used();
if (reserved != 0) {
log_info(gc, metaspace)("Metaspace: " SIZE_FORMAT "%s reserved, " SIZE_FORMAT "%s (%.2f%%) committed, "

View File

@ -111,7 +111,6 @@ void EpsilonMonitoringSupport::update_counters() {
_heap_counters->update_all();
_space_counters->update_all(capacity, used);
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
}
}

View File

@ -35,6 +35,7 @@ G1HeapTransition::Data::Data(G1CollectedHeap* g1_heap) :
_old_length(g1_heap->old_regions_count()),
_archive_length(g1_heap->archive_regions_count()),
_humongous_length(g1_heap->humongous_regions_count()),
_meta_sizes(MetaspaceUtils::get_combined_statistics()),
_eden_length_per_node(NULL),
_survivor_length_per_node(NULL) {

View File

@ -26,7 +26,7 @@
#define SHARE_GC_G1_G1HEAPTRANSITION_HPP
#include "gc/shared/plab.hpp"
#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
#include "memory/metaspaceStats.hpp"
class G1CollectedHeap;
@ -37,7 +37,7 @@ class G1HeapTransition {
size_t _old_length;
size_t _archive_length;
size_t _humongous_length;
const metaspace::MetaspaceSizesSnapshot _meta_sizes;
const MetaspaceCombinedStats _meta_sizes;
// Only includes current eden regions.
uint* _eden_length_per_node;

View File

@ -303,7 +303,6 @@ void G1MonitoringSupport::update_sizes() {
_old_gen_counters->update_all();
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
}
}

View File

@ -184,7 +184,6 @@ void ParallelScavengeHeap::update_counters() {
young_gen()->update_counters();
old_gen()->update_counters();
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
}
size_t ParallelScavengeHeap::capacity() const {

View File

@ -128,25 +128,12 @@ GCHeapSummary CollectedHeap::create_heap_summary() {
}
MetaspaceSummary CollectedHeap::create_metaspace_summary() {
const MetaspaceSizes meta_space(
MetaspaceUtils::committed_bytes(),
MetaspaceUtils::used_bytes(),
MetaspaceUtils::reserved_bytes());
const MetaspaceSizes data_space(
MetaspaceUtils::committed_bytes(Metaspace::NonClassType),
MetaspaceUtils::used_bytes(Metaspace::NonClassType),
MetaspaceUtils::reserved_bytes(Metaspace::NonClassType));
const MetaspaceSizes class_space(
MetaspaceUtils::committed_bytes(Metaspace::ClassType),
MetaspaceUtils::used_bytes(Metaspace::ClassType),
MetaspaceUtils::reserved_bytes(Metaspace::ClassType));
const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary =
MetaspaceUtils::chunk_free_list_summary(Metaspace::NonClassType);
const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary =
MetaspaceUtils::chunk_free_list_summary(Metaspace::ClassType);
return MetaspaceSummary(MetaspaceGC::capacity_until_GC(), meta_space, data_space, class_space,
return MetaspaceSummary(MetaspaceGC::capacity_until_GC(),
MetaspaceUtils::get_combined_statistics(),
ms_chunk_free_list_summary, class_chunk_free_list_summary);
}

View File

@ -26,6 +26,7 @@
#define SHARE_GC_SHARED_GCHEAPSUMMARY_HPP
#include "memory/allocation.hpp"
#include "memory/metaspaceStats.hpp"
#include "memory/metaspaceChunkFreeListSummary.hpp"
class VirtualSpaceSummary : public StackObj {
@ -61,21 +62,6 @@ public:
size_t size() const { return (uintptr_t)_end - (uintptr_t)_start; }
};
class MetaspaceSizes : public StackObj {
size_t _committed;
size_t _used;
size_t _reserved;
public:
MetaspaceSizes() : _committed(0), _used(0), _reserved(0) {}
MetaspaceSizes(size_t committed, size_t used, size_t reserved) :
_committed(committed), _used(used), _reserved(reserved) {}
size_t committed() const { return _committed; }
size_t used() const { return _used; }
size_t reserved() const { return _reserved; }
};
class GCHeapSummary;
class PSHeapSummary;
class G1HeapSummary;
@ -147,39 +133,29 @@ class G1HeapSummary : public GCHeapSummary {
class MetaspaceSummary : public StackObj {
size_t _capacity_until_GC;
MetaspaceSizes _meta_space;
MetaspaceSizes _data_space;
MetaspaceSizes _class_space;
MetaspaceCombinedStats _stats;
MetaspaceChunkFreeListSummary _metaspace_chunk_free_list_summary;
MetaspaceChunkFreeListSummary _class_chunk_free_list_summary;
public:
MetaspaceSummary() :
_capacity_until_GC(0),
_meta_space(),
_data_space(),
_class_space(),
_stats(),
_metaspace_chunk_free_list_summary(),
_class_chunk_free_list_summary()
{}
MetaspaceSummary(size_t capacity_until_GC,
const MetaspaceSizes& meta_space,
const MetaspaceSizes& data_space,
const MetaspaceSizes& class_space,
const MetaspaceCombinedStats& stats,
const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary,
const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary) :
_capacity_until_GC(capacity_until_GC),
_meta_space(meta_space),
_data_space(data_space),
_class_space(class_space),
_stats(stats),
_metaspace_chunk_free_list_summary(metaspace_chunk_free_list_summary),
_class_chunk_free_list_summary(class_chunk_free_list_summary)
{}
size_t capacity_until_GC() const { return _capacity_until_GC; }
const MetaspaceSizes& meta_space() const { return _meta_space; }
const MetaspaceSizes& data_space() const { return _data_space; }
const MetaspaceSizes& class_space() const { return _class_space; }
const MetaspaceCombinedStats& stats() const { return _stats; }
const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary() const {
return _metaspace_chunk_free_list_summary;

View File

@ -265,13 +265,11 @@ void GCTracer::send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary
heap_summary.accept(&visitor);
}
static JfrStructMetaspaceSizes to_struct(const MetaspaceSizes& sizes) {
static JfrStructMetaspaceSizes to_struct(const MetaspaceStats& sizes) {
JfrStructMetaspaceSizes meta_sizes;
meta_sizes.set_committed(sizes.committed());
meta_sizes.set_used(sizes.used());
meta_sizes.set_reserved(sizes.reserved());
return meta_sizes;
}
@ -281,9 +279,9 @@ void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceS
e.set_gcId(GCId::current());
e.set_when((u1) when);
e.set_gcThreshold(meta_space_summary.capacity_until_GC());
e.set_metaspace(to_struct(meta_space_summary.meta_space()));
e.set_dataSpace(to_struct(meta_space_summary.data_space()));
e.set_classSpace(to_struct(meta_space_summary.class_space()));
e.set_metaspace(to_struct(meta_space_summary.stats())); // total stats (class + nonclass)
e.set_dataSpace(to_struct(meta_space_summary.stats().non_class_space_stats())); // "dataspace" aka non-class space
e.set_classSpace(to_struct(meta_space_summary.stats().class_space_stats()));
e.commit();
}
}

View File

@ -57,7 +57,6 @@
#include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workgroup.hpp"
#include "memory/iterator.hpp"
#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
#include "memory/metaspaceCounters.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/resourceArea.hpp"
@ -1228,7 +1227,6 @@ void GenCollectedHeap::gc_epilogue(bool full) {
generation_iterate(&blk, false); // not old-to-young.
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
};
#ifndef PRODUCT

View File

@ -26,7 +26,8 @@
#ifndef SHARE_GC_SHARED_PREGCVALUES_HPP
#define SHARE_GC_SHARED_PREGCVALUES_HPP
#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
#include "memory/metaspaceStats.hpp"
#include "memory/metaspaceUtils.hpp"
// Simple class for storing info about the heap at the start of GC, to be used
// after GC for comparison/printing.
@ -47,7 +48,8 @@ public:
_from_used(from_used),
_from_capacity(from_capacity),
_old_gen_used(old_gen_used),
_old_gen_capacity(old_gen_capacity) { }
_old_gen_capacity(old_gen_capacity),
_meta_sizes(MetaspaceUtils::get_combined_statistics()){ }
size_t young_gen_used() const { return _young_gen_used; }
size_t young_gen_capacity() const { return _young_gen_capacity; }
@ -57,7 +59,7 @@ public:
size_t from_capacity() const { return _from_capacity; }
size_t old_gen_used() const { return _old_gen_used; }
size_t old_gen_capacity() const { return _old_gen_capacity; }
const metaspace::MetaspaceSizesSnapshot& metaspace_sizes() const { return _meta_sizes; }
const MetaspaceCombinedStats& metaspace_sizes() const { return _meta_sizes; }
private:
const size_t _young_gen_used;
@ -68,7 +70,7 @@ private:
const size_t _from_capacity;
const size_t _old_gen_used;
const size_t _old_gen_capacity;
const metaspace::MetaspaceSizesSnapshot _meta_sizes;
const MetaspaceCombinedStats _meta_sizes;
};
#endif // SHARE_GC_SHARED_PREGCVALUES_HPP

View File

@ -41,6 +41,7 @@
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
#include "memory/iterator.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/metaspaceStats.hpp"
#include "memory/universe.hpp"
#include "runtime/atomic.hpp"
@ -187,8 +188,7 @@ void ShenandoahControlThread::run_service() {
heap->reset_bytes_allocated_since_gc_start();
// Use default constructor to snapshot the Metaspace state before GC.
metaspace::MetaspaceSizesSnapshot meta_sizes;
MetaspaceCombinedStats meta_sizes = MetaspaceUtils::get_combined_statistics();
// If GC was requested, we are sampling the counters even without actual triggers
// from allocation machinery. This captures GC phases more accurately.

View File

@ -101,6 +101,5 @@ void ShenandoahMonitoringSupport::update_counters() {
_heap_region_counters->update();
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
}
}

View File

@ -89,7 +89,6 @@ void ZServiceabilityCounters::update_sizes() {
_space_counters.update_used(used);
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
}
}

View File

@ -1211,12 +1211,13 @@ void ZStatNMethods::print() {
// Stat metaspace
//
void ZStatMetaspace::print() {
MetaspaceCombinedStats stats = MetaspaceUtils::get_combined_statistics();
log_info(gc, metaspace)("Metaspace: "
SIZE_FORMAT "M used, "
SIZE_FORMAT "M committed, " SIZE_FORMAT "M reserved",
MetaspaceUtils::used_bytes() / M,
MetaspaceUtils::committed_bytes() / M,
MetaspaceUtils::reserved_bytes() / M);
stats.used() / M,
stats.committed() / M,
stats.reserved() / M);
}
//

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021 SAP SE. 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
@ -33,14 +34,15 @@
#include "memory/metaspace/chunkHeaderPool.hpp"
#include "memory/metaspace/chunkManager.hpp"
#include "memory/metaspace/commitLimiter.hpp"
#include "memory/metaspace/internalStats.hpp"
#include "memory/metaspace/metaspaceCommon.hpp"
#include "memory/metaspace/metaspaceContext.hpp"
#include "memory/metaspace/metaspaceReporter.hpp"
#include "memory/metaspace/metaspaceSettings.hpp"
#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
#include "memory/metaspace/runningCounters.hpp"
#include "memory/metaspace/virtualSpaceList.hpp"
#include "memory/metaspaceTracer.hpp"
#include "memory/metaspaceStats.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
@ -87,8 +89,65 @@ size_t MetaspaceUtils::committed_words(Metaspace::MetadataType mdtype) {
return mdtype == Metaspace::ClassType ? RunningCounters::committed_words_class() : RunningCounters::committed_words_nonclass();
}
void MetaspaceUtils::print_metaspace_change(const metaspace::MetaspaceSizesSnapshot& pre_meta_values) {
const metaspace::MetaspaceSizesSnapshot meta_values;
// Helper for get_statistics()
static void get_values_for(Metaspace::MetadataType mdtype, size_t* reserved, size_t* committed, size_t* used) {
#define w2b(x) (x * sizeof(MetaWord))
if (mdtype == Metaspace::ClassType) {
*reserved = w2b(RunningCounters::reserved_words_class());
*committed = w2b(RunningCounters::committed_words_class());
*used = w2b(RunningCounters::used_words_class());
} else {
*reserved = w2b(RunningCounters::reserved_words_nonclass());
*committed = w2b(RunningCounters::committed_words_nonclass());
*used = w2b(RunningCounters::used_words_nonclass());
}
#undef w2b
}
// Retrieve all statistics in one go; make sure the values are consistent.
MetaspaceStats MetaspaceUtils::get_statistics(Metaspace::MetadataType mdtype) {
// Consistency:
// This function reads three values (reserved, committed, used) from different counters. These counters
// may (very rarely) be out of sync. This has been a source for intermittent test errors in the past
// (see e.g. JDK-8237872, JDK-8151460).
// - reserved and committed counter are updated under protection of Metaspace_lock; an inconsistency
// between them can be the result of a dirty read.
// - used is an atomic counter updated outside any lock range; there is no way to guarantee
// a clean read wrt the other two values.
// Reading these values under lock protection would would only help for the first case. Therefore
// we don't bother and just re-read several times, then give up and correct the values.
size_t r = 0, c = 0, u = 0; // Note: byte values.
get_values_for(mdtype, &r, &c, &u);
int retries = 10;
// If the first retrieval resulted in inconsistent values, retry a bit...
while ((r < c || c < u) && --retries >= 0) {
get_values_for(mdtype, &r, &c, &u);
}
if (c < u || r < c) { // still inconsistent.
// ... but not endlessly. If we don't get consistent values, correct them on the fly.
// The logic here is that we trust the used counter - its an atomic counter and whatever we see
// must have been the truth once - and from that we reconstruct a likely set of committed/reserved
// values.
metaspace::InternalStats::inc_num_inconsistent_stats();
if (c < u) {
c = align_up(u, Metaspace::commit_alignment());
}
if (r < c) {
r = align_up(c, Metaspace::reserve_alignment());
}
}
return MetaspaceStats(r, c, u);
}
MetaspaceCombinedStats MetaspaceUtils::get_combined_statistics() {
return MetaspaceCombinedStats(get_statistics(Metaspace::ClassType), get_statistics(Metaspace::NonClassType));
}
void MetaspaceUtils::print_metaspace_change(const MetaspaceCombinedStats& pre_meta_values) {
// Get values now:
const MetaspaceCombinedStats meta_values = get_combined_statistics();
// We print used and committed since these are the most useful at-a-glance vitals for Metaspace:
// - used tells you how much memory is actually used for metadata
@ -150,24 +209,23 @@ void MetaspaceUtils::print_report(outputStream* out, size_t scale) {
void MetaspaceUtils::print_on(outputStream* out) {
// Used from all GCs. It first prints out totals, then, separately, the class space portion.
MetaspaceCombinedStats stats = get_combined_statistics();
out->print_cr(" Metaspace "
"used " SIZE_FORMAT "K, "
"committed " SIZE_FORMAT "K, "
"reserved " SIZE_FORMAT "K",
used_bytes()/K,
committed_bytes()/K,
reserved_bytes()/K);
stats.used()/K,
stats.committed()/K,
stats.reserved()/K);
if (Metaspace::using_class_space()) {
const Metaspace::MetadataType ct = Metaspace::ClassType;
out->print_cr(" class space "
"used " SIZE_FORMAT "K, "
"committed " SIZE_FORMAT "K, "
"reserved " SIZE_FORMAT "K",
used_bytes(ct)/K,
committed_bytes(ct)/K,
reserved_bytes(ct)/K);
stats.class_space_stats().used()/K,
stats.class_space_stats().committed()/K,
stats.class_space_stats().reserved()/K);
}
}
@ -870,7 +928,6 @@ void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_s
MetaspaceUtils::print_basic_report(&ls, 0);
}
// TODO: this exception text may be wrong and misleading. This needs more thinking. See JDK-8252189.
bool out_of_compressed_class_space = false;
if (is_class_space_allocation(mdtype)) {
ClassLoaderMetaspace* metaspace = loader_data->metaspace_non_null();

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021 SAP SE. 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
@ -36,10 +37,6 @@ class Mutex;
class outputStream;
class ReservedSpace;
namespace metaspace {
class MetaspaceSizesSnapshot;
}
////////////////// Metaspace ///////////////////////
// Namespace for important central static functions

View File

@ -94,6 +94,9 @@ class InternalStats : public AllStatic {
\
/* Number of times we did a purge */ \
x(num_purges) \
\
/* Number of times we read inconsistent stats. */ \
x(num_inconsistent_stats) \
// Note: We use uintx since 32bit platforms lack 64bit atomic add; this increases
// the possibility of counter overflows but the probability is very low for any counter

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Twitter, Inc.
* 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"
#include "memory/metaspace.hpp"
#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
#include "memory/metaspaceUtils.hpp"
namespace metaspace {
MetaspaceSizesSnapshot::MetaspaceSizesSnapshot() :
_used(MetaspaceUtils::used_bytes()),
_committed(MetaspaceUtils::committed_bytes()),
_non_class_used(MetaspaceUtils::used_bytes(Metaspace::NonClassType)),
_non_class_committed(MetaspaceUtils::committed_bytes(Metaspace::NonClassType)),
_class_used(MetaspaceUtils::used_bytes(Metaspace::ClassType)),
_class_committed(MetaspaceUtils::committed_bytes(Metaspace::ClassType))
{}
} // namespace metaspace

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Twitter, Inc.
* 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.
*
*/
#ifndef SHARE_MEMORY_METASPACE_METASPACESIZESSNAPSHOT_HPP
#define SHARE_MEMORY_METASPACE_METASPACESIZESSNAPSHOT_HPP
#include "utilities/globalDefinitions.hpp"
namespace metaspace {
// Todo: clean up after jep387, see JDK-8251392
class MetaspaceSizesSnapshot {
public:
MetaspaceSizesSnapshot();
size_t used() const { return _used; }
size_t committed() const { return _committed; }
size_t non_class_used() const { return _non_class_used; }
size_t non_class_committed() const { return _non_class_committed; }
size_t class_used() const { return _class_used; }
size_t class_committed() const { return _class_committed; }
private:
const size_t _used;
const size_t _committed;
const size_t _non_class_used;
const size_t _non_class_committed;
const size_t _class_used;
const size_t _class_committed;
};
} // namespace metaspace
#endif // SHARE_MEMORY_METASPACE_METASPACESIZESSNAPSHOT_HPP

View File

@ -25,13 +25,14 @@
#include "precompiled.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceCounters.hpp"
#include "memory/metaspaceStats.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/globals.hpp"
#include "runtime/perfData.hpp"
#include "utilities/exceptions.hpp"
class MetaspacePerfCounters: public CHeapObj<mtMetaspace> {
class MetaspacePerfCounters {
friend class VMStructs;
PerfVariable* _capacity;
PerfVariable* _used;
@ -48,88 +49,40 @@ class MetaspacePerfCounters: public CHeapObj<mtMetaspace> {
}
public:
MetaspacePerfCounters(const char* ns, size_t min_capacity, size_t curr_capacity, size_t max_capacity, size_t used) {
MetaspacePerfCounters() : _capacity(NULL), _used(NULL), _max_capacity(NULL) {}
void initialize(const char* ns) {
assert(_capacity == NULL, "Only initialize once");
EXCEPTION_MARK;
ResourceMark rm;
create_constant(ns, "minCapacity", min_capacity, THREAD);
_capacity = create_variable(ns, "capacity", curr_capacity, THREAD);
_max_capacity = create_variable(ns, "maxCapacity", max_capacity, THREAD);
_used = create_variable(ns, "used", used, THREAD);
create_constant(ns, "minCapacity", 0, THREAD); // min_capacity makes little sense in the context of metaspace
_capacity = create_variable(ns, "capacity", 0, THREAD);
_max_capacity = create_variable(ns, "maxCapacity", 0, THREAD);
_used = create_variable(ns, "used", 0, THREAD);
}
void update(size_t capacity, size_t max_capacity, size_t used) {
_capacity->set_value(capacity);
_max_capacity->set_value(max_capacity);
_used->set_value(used);
void update(const MetaspaceStats& stats) {
_capacity->set_value(stats.committed());
_max_capacity->set_value(stats.reserved());
_used->set_value(stats.used());
}
};
MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL;
size_t MetaspaceCounters::used() {
return MetaspaceUtils::used_bytes();
}
size_t MetaspaceCounters::capacity() {
return MetaspaceUtils::committed_bytes();
}
size_t MetaspaceCounters::max_capacity() {
return MetaspaceUtils::reserved_bytes();
}
static MetaspacePerfCounters g_meta_space_perf_counters; // class + nonclass
static MetaspacePerfCounters g_class_space_perf_counters;
void MetaspaceCounters::initialize_performance_counters() {
if (UsePerfData) {
assert(_perf_counters == NULL, "Should only be initialized once");
size_t min_capacity = 0;
_perf_counters = new MetaspacePerfCounters("metaspace", min_capacity,
capacity(), max_capacity(), used());
g_meta_space_perf_counters.initialize("metaspace");
g_class_space_perf_counters.initialize("compressedclassspace");
update_performance_counters();
}
}
void MetaspaceCounters::update_performance_counters() {
if (UsePerfData) {
assert(_perf_counters != NULL, "Should be initialized");
_perf_counters->update(capacity(), max_capacity(), used());
}
}
MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL;
size_t CompressedClassSpaceCounters::used() {
return MetaspaceUtils::used_bytes(Metaspace::ClassType);
}
size_t CompressedClassSpaceCounters::capacity() {
return MetaspaceUtils::committed_bytes(Metaspace::ClassType);
}
size_t CompressedClassSpaceCounters::max_capacity() {
return MetaspaceUtils::reserved_bytes(Metaspace::ClassType);
}
void CompressedClassSpaceCounters::update_performance_counters() {
if (UsePerfData && UseCompressedClassPointers) {
assert(_perf_counters != NULL, "Should be initialized");
_perf_counters->update(capacity(), max_capacity(), used());
}
}
void CompressedClassSpaceCounters::initialize_performance_counters() {
if (UsePerfData) {
assert(_perf_counters == NULL, "Should only be initialized once");
const char* ns = "compressedclassspace";
if (UseCompressedClassPointers) {
size_t min_capacity = 0;
_perf_counters = new MetaspacePerfCounters(ns, min_capacity, capacity(),
max_capacity(), used());
} else {
_perf_counters = new MetaspacePerfCounters(ns, 0, 0, 0, 0);
}
g_meta_space_perf_counters.update(MetaspaceUtils::get_combined_statistics());
g_class_space_perf_counters.update(MetaspaceUtils::get_statistics(Metaspace::ClassType));
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 SAP SE. 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
@ -27,26 +28,9 @@
#include "memory/allocation.hpp"
class MetaspacePerfCounters;
// Perf Counters for Metaspace
// Todo: clean up after jep387, see JDK-8251392
class MetaspaceCounters: public AllStatic {
static MetaspacePerfCounters* _perf_counters;
static size_t used();
static size_t capacity();
static size_t max_capacity();
public:
static void initialize_performance_counters();
static void update_performance_counters();
};
class CompressedClassSpaceCounters: public AllStatic {
static MetaspacePerfCounters* _perf_counters;
static size_t used();
static size_t capacity();
static size_t max_capacity();
public:
static void initialize_performance_counters();
static void update_performance_counters();

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 SAP SE. 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
* 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.
*
*/
#ifndef SHARE_MEMORY_METASPACESTATS_HPP
#define SHARE_MEMORY_METASPACESTATS_HPP
#include "utilities/globalDefinitions.hpp"
// Data holder classes for metaspace statistics.
//
// - MetaspaceStats: keeps reserved, committed and used byte counters;
// retrieve with MetaspaceUtils::get_statistics(MetadataType) for either class space
// or non-class space
//
// - MetaspaceCombinedStats: keeps reserved, committed and used byte counters, seperately for both class- and non-class-space;
// retrieve with MetaspaceUtils::get_combined_statistics()
// (Note: just for NMT these objects need to be mutable)
class MetaspaceStats {
size_t _reserved;
size_t _committed;
size_t _used;
public:
MetaspaceStats() : _reserved(0), _committed(0), _used(0) {}
MetaspaceStats(size_t r, size_t c, size_t u) : _reserved(r), _committed(c), _used(u) {}
size_t used() const { return _used; }
size_t committed() const { return _committed; }
size_t reserved() const { return _reserved; }
};
// Class holds combined statistics for both non-class and class space.
class MetaspaceCombinedStats : public MetaspaceStats {
MetaspaceStats _cstats; // class space stats
MetaspaceStats _ncstats; // non-class space stats
public:
MetaspaceCombinedStats() {}
MetaspaceCombinedStats(const MetaspaceStats& cstats, const MetaspaceStats& ncstats) :
MetaspaceStats(cstats.reserved() + ncstats.reserved(),
cstats.committed() + ncstats.committed(),
cstats.used() + ncstats.used()),
_cstats(cstats), _ncstats(ncstats)
{}
const MetaspaceStats& class_space_stats() const { return _cstats; }
const MetaspaceStats& non_class_space_stats() const { return _ncstats; }
size_t class_used() const { return _cstats.used(); }
size_t class_committed() const { return _cstats.committed(); }
size_t class_reserved() const { return _cstats.reserved(); }
size_t non_class_used() const { return _ncstats.used(); }
size_t non_class_committed() const { return _ncstats.committed(); }
size_t non_class_reserved() const { return _ncstats.reserved(); }
};
#endif // SHARE_MEMORY_METASPACESTATS_HPP

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 SAP SE. 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
@ -26,6 +27,7 @@
#include "memory/metaspace.hpp"
#include "memory/metaspaceChunkFreeListSummary.hpp"
#include "memory/metaspaceStats.hpp"
class outputStream;
@ -115,13 +117,17 @@ public:
static size_t reserved_bytes() { return reserved_words() * BytesPerWord; }
static size_t reserved_bytes(Metaspace::MetadataType mdtype) { return reserved_words(mdtype) * BytesPerWord; }
// Retrieve all statistics in one go; make sure the values are consistent.
static MetaspaceStats get_statistics(Metaspace::MetadataType mdtype);
static MetaspaceCombinedStats get_combined_statistics();
// (See JDK-8251342). Implement or Consolidate.
static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype) {
return MetaspaceChunkFreeListSummary(0,0,0,0,0,0,0,0);
}
// Log change in used metadata.
static void print_metaspace_change(const metaspace::MetaspaceSizesSnapshot& pre_meta_values);
static void print_metaspace_change(const MetaspaceCombinedStats& pre_meta_values);
// This will print out a basic metaspace usage report but
// unlike print_report() is guaranteed not to lock or to walk the CLDG.

View File

@ -752,7 +752,6 @@ jint universe_init() {
// Initialize performance counters for metaspaces
MetaspaceCounters::initialize_performance_counters();
CompressedClassSpaceCounters::initialize_performance_counters();
// Checks 'AfterMemoryInit' constraints.
if (!JVMFlagLimit::check_all_constraints(JVMFlagConstraintPhase::AfterMemoryInit)) {

View File

@ -25,6 +25,7 @@
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "memory/allocation.hpp"
#include "memory/metaspaceUtils.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
#include "services/memBaseline.hpp"
@ -147,7 +148,7 @@ class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
bool MemBaseline::baseline_summary() {
MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
MetaspaceSnapshot::snapshot(_metaspace_snapshot);
_metaspace_stats = MetaspaceUtils::get_combined_statistics();
return true;
}

View File

@ -27,6 +27,7 @@
#if INCLUDE_NMT
#include "memory/metaspaceStats.hpp"
#include "runtime/mutex.hpp"
#include "services/mallocSiteTable.hpp"
#include "services/mallocTracker.hpp"
@ -61,7 +62,7 @@ class MemBaseline {
// Summary information
MallocMemorySnapshot _malloc_memory_snapshot;
VirtualMemorySnapshot _virtual_memory_snapshot;
MetaspaceSnapshot _metaspace_snapshot;
MetaspaceCombinedStats _metaspace_stats;
size_t _instance_class_count;
size_t _array_class_count;
@ -101,8 +102,8 @@ class MemBaseline {
return &_virtual_memory_snapshot;
}
MetaspaceSnapshot* metaspace_snapshot() {
return &_metaspace_snapshot;
const MetaspaceCombinedStats& metaspace_stats() const {
return _metaspace_stats;
}
MallocSiteIterator malloc_sites(SortingOrder order);

View File

@ -223,24 +223,18 @@ void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const {
outputStream* out = output();
const char* scale = current_scale();
size_t committed = MetaspaceUtils::committed_bytes(type);
size_t used = MetaspaceUtils::used_bytes(type);
const MetaspaceStats stats = MetaspaceUtils::get_statistics(type);
// The answer to "what is free" in metaspace is complex and cannot be answered with a single number.
// Free as in available to all loaders? Free, pinned to one loader? For now, keep it simple.
size_t free = committed - used;
assert(committed >= used + free, "Sanity");
size_t waste = committed - (used + free);
size_t waste = stats.committed() - stats.used();
float waste_percentage = stats.committed() > 0 ? (((float)waste * 100)/stats.committed()) : 0.0f;
out->print_cr("%27s ( %s)", " ", name);
out->print("%27s ( ", " ");
print_total(MetaspaceUtils::reserved_bytes(type), committed);
print_total(stats.reserved(), stats.committed());
out->print_cr(")");
out->print_cr("%27s ( used=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(used), scale);
out->print_cr("%27s ( free=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(free), scale);
out->print_cr("%27s ( used=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(stats.used()), scale);
out->print_cr("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%)", " ", amount_in_current_scale(waste),
scale, ((float)waste * 100)/committed);
scale, waste_percentage);
}
void MemDetailReporter::report_detail() {
@ -408,10 +402,10 @@ void MemSummaryDiffReporter::report_diff() {
diff_summary_of_type(flag,
_early_baseline.malloc_memory(flag),
_early_baseline.virtual_memory(flag),
_early_baseline.metaspace_snapshot(),
_early_baseline.metaspace_stats(),
_current_baseline.malloc_memory(flag),
_current_baseline.virtual_memory(flag),
_current_baseline.metaspace_snapshot());
_current_baseline.metaspace_stats());
}
}
@ -474,9 +468,9 @@ void MemSummaryDiffReporter::print_virtual_memory_diff(size_t current_reserved,
void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag,
const MallocMemory* early_malloc, const VirtualMemory* early_vm,
const MetaspaceSnapshot* early_ms,
const MetaspaceCombinedStats& early_ms,
const MallocMemory* current_malloc, const VirtualMemory* current_vm,
const MetaspaceSnapshot* current_ms) const {
const MetaspaceCombinedStats& current_ms) const {
outputStream* out = output();
const char* scale = current_scale();
@ -615,70 +609,54 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag,
}
out->print_cr(")");
} else if (flag == mtClass) {
assert(current_ms != NULL && early_ms != NULL, "Sanity");
print_metaspace_diff(current_ms, early_ms);
}
out->print_cr(" ");
}
}
void MemSummaryDiffReporter::print_metaspace_diff(const MetaspaceSnapshot* current_ms,
const MetaspaceSnapshot* early_ms) const {
print_metaspace_diff(Metaspace::NonClassType, current_ms, early_ms);
void MemSummaryDiffReporter::print_metaspace_diff(const MetaspaceCombinedStats& current_ms,
const MetaspaceCombinedStats& early_ms) const {
print_metaspace_diff("Metadata", current_ms.non_class_space_stats(), early_ms.non_class_space_stats());
if (Metaspace::using_class_space()) {
print_metaspace_diff(Metaspace::ClassType, current_ms, early_ms);
print_metaspace_diff("Class space", current_ms.class_space_stats(), early_ms.class_space_stats());
}
}
void MemSummaryDiffReporter::print_metaspace_diff(Metaspace::MetadataType type,
const MetaspaceSnapshot* current_ms,
const MetaspaceSnapshot* early_ms) const {
const char* name = (type == Metaspace::NonClassType) ?
"Metadata: " : "Class space:";
void MemSummaryDiffReporter::print_metaspace_diff(const char* header,
const MetaspaceStats& current_stats,
const MetaspaceStats& early_stats) const {
outputStream* out = output();
const char* scale = current_scale();
out->print_cr("%27s ( %s)", " ", name);
out->print_cr("%27s: ( %s)", " ", header);
out->print("%27s ( ", " ");
print_virtual_memory_diff(current_ms->reserved_in_bytes(type),
current_ms->committed_in_bytes(type),
early_ms->reserved_in_bytes(type),
early_ms->committed_in_bytes(type));
print_virtual_memory_diff(current_stats.reserved(),
current_stats.committed(),
early_stats.reserved(),
early_stats.committed());
out->print_cr(")");
long diff_used = diff_in_current_scale(current_ms->used_in_bytes(type),
early_ms->used_in_bytes(type));
long diff_free = diff_in_current_scale(current_ms->free_in_bytes(type),
early_ms->free_in_bytes(type));
long diff_used = diff_in_current_scale(current_stats.used(),
early_stats.used());
size_t current_waste = current_ms->committed_in_bytes(type)
- (current_ms->used_in_bytes(type) + current_ms->free_in_bytes(type));
size_t early_waste = early_ms->committed_in_bytes(type)
- (early_ms->used_in_bytes(type) + early_ms->free_in_bytes(type));
size_t current_waste = current_stats.committed() - current_stats.used();
size_t early_waste = early_stats.committed() - early_stats.used();
long diff_waste = diff_in_current_scale(current_waste, early_waste);
// Diff used
out->print("%27s ( used=" SIZE_FORMAT "%s", " ",
amount_in_current_scale(current_ms->used_in_bytes(type)), scale);
amount_in_current_scale(current_stats.used()), scale);
if (diff_used != 0) {
out->print(" %+ld%s", diff_used, scale);
}
out->print_cr(")");
// Diff free
out->print("%27s ( free=" SIZE_FORMAT "%s", " ",
amount_in_current_scale(current_ms->free_in_bytes(type)), scale);
if (diff_free != 0) {
out->print(" %+ld%s", diff_free, scale);
}
out->print_cr(")");
// Diff waste
const float waste_percentage = current_stats.committed() == 0 ? 0.0f :
(current_waste * 100.0f) / current_stats.committed();
out->print("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%", " ",
amount_in_current_scale(current_waste), scale,
((float)current_waste * 100) / current_ms->committed_in_bytes(type));
amount_in_current_scale(current_waste), scale, waste_percentage);
if (diff_waste != 0) {
out->print(" %+ld%s", diff_waste, scale);
}

View File

@ -180,9 +180,9 @@ class MemSummaryDiffReporter : public MemReporterBase {
// report the comparison of each memory type
void diff_summary_of_type(MEMFLAGS type,
const MallocMemory* early_malloc, const VirtualMemory* early_vm,
const MetaspaceSnapshot* early_ms,
const MetaspaceCombinedStats& early_ms,
const MallocMemory* current_malloc, const VirtualMemory* current_vm,
const MetaspaceSnapshot* current_ms) const;
const MetaspaceCombinedStats& current_ms) const;
protected:
void print_malloc_diff(size_t current_amount, size_t current_count,
@ -192,10 +192,11 @@ class MemSummaryDiffReporter : public MemReporterBase {
void print_arena_diff(size_t current_amount, size_t current_count,
size_t early_amount, size_t early_count) const;
void print_metaspace_diff(const MetaspaceSnapshot* current_ms,
const MetaspaceSnapshot* early_ms) const;
void print_metaspace_diff(Metaspace::MetadataType type,
const MetaspaceSnapshot* current_ms, const MetaspaceSnapshot* early_ms) const;
void print_metaspace_diff(const MetaspaceCombinedStats& current_ms,
const MetaspaceCombinedStats& early_ms) const;
void print_metaspace_diff(const char* header,
const MetaspaceStats& current_ms,
const MetaspaceStats& early_ms) const;
};
/*

View File

@ -188,8 +188,8 @@ MetaspacePool::MetaspacePool() :
MemoryPool("Metaspace", NonHeap, 0, calculate_max_size(), true, false) { }
MemoryUsage MetaspacePool::get_memory_usage() {
size_t committed = MetaspaceUtils::committed_bytes();
return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
MetaspaceCombinedStats stats = MetaspaceUtils::get_combined_statistics();
return MemoryUsage(initial_size(), stats.used(), stats.committed(), max_size());
}
size_t MetaspacePool::used_in_bytes() {
@ -209,6 +209,6 @@ size_t CompressedKlassSpacePool::used_in_bytes() {
}
MemoryUsage CompressedKlassSpacePool::get_memory_usage() {
size_t committed = MetaspaceUtils::committed_bytes(Metaspace::ClassType);
return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
MetaspaceStats stats = MetaspaceUtils::get_statistics(Metaspace::ClassType);
return MemoryUsage(initial_size(), stats.used(), stats.committed(), max_size());
}

View File

@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
#include "logging/log.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/metaspaceStats.hpp"
#include "runtime/os.hpp"
#include "runtime/threadCritical.hpp"
#include "services/memTracker.hpp"
@ -693,34 +693,3 @@ bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel
return true;
}
// Metaspace Support
MetaspaceSnapshot::MetaspaceSnapshot() {
for (int index = (int)Metaspace::ClassType; index < (int)Metaspace::MetadataTypeCount; index ++) {
Metaspace::MetadataType type = (Metaspace::MetadataType)index;
assert_valid_metadata_type(type);
_reserved_in_bytes[type] = 0;
_committed_in_bytes[type] = 0;
_used_in_bytes[type] = 0;
_free_in_bytes[type] = 0;
}
}
void MetaspaceSnapshot::snapshot(Metaspace::MetadataType type, MetaspaceSnapshot& mss) {
assert_valid_metadata_type(type);
mss._reserved_in_bytes[type] = MetaspaceUtils::reserved_bytes(type);
mss._committed_in_bytes[type] = MetaspaceUtils::committed_bytes(type);
mss._used_in_bytes[type] = MetaspaceUtils::used_bytes(type);
// The answer to "what is free" in metaspace is complex and cannot be answered with a single number.
// Free as in available to all loaders? Free, pinned to one loader? For now, keep it simple.
mss._free_in_bytes[type] = mss._committed_in_bytes[type] - mss._used_in_bytes[type];
}
void MetaspaceSnapshot::snapshot(MetaspaceSnapshot& mss) {
snapshot(Metaspace::NonClassType, mss);
if (Metaspace::using_class_space()) {
snapshot(Metaspace::ClassType, mss);
}
}

View File

@ -28,7 +28,8 @@
#if INCLUDE_NMT
#include "memory/allocation.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspace.hpp" // For MetadataType
#include "memory/metaspaceStats.hpp"
#include "services/allocationSite.hpp"
#include "services/nmtCommon.hpp"
#include "utilities/linkedlist.hpp"
@ -398,32 +399,6 @@ class VirtualMemoryTracker : AllStatic {
static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* _reserved_regions;
};
// Todo: clean up after jep387, see JDK-8251392
class MetaspaceSnapshot : public ResourceObj {
private:
size_t _reserved_in_bytes[Metaspace::MetadataTypeCount];
size_t _committed_in_bytes[Metaspace::MetadataTypeCount];
size_t _used_in_bytes[Metaspace::MetadataTypeCount];
size_t _free_in_bytes[Metaspace::MetadataTypeCount];
public:
MetaspaceSnapshot();
size_t reserved_in_bytes(Metaspace::MetadataType type) const { assert_valid_metadata_type(type); return _reserved_in_bytes[type]; }
size_t committed_in_bytes(Metaspace::MetadataType type) const { assert_valid_metadata_type(type); return _committed_in_bytes[type]; }
size_t used_in_bytes(Metaspace::MetadataType type) const { assert_valid_metadata_type(type); return _used_in_bytes[type]; }
size_t free_in_bytes(Metaspace::MetadataType type) const { assert_valid_metadata_type(type); return _free_in_bytes[type]; }
static void snapshot(MetaspaceSnapshot& s);
private:
static void snapshot(Metaspace::MetadataType type, MetaspaceSnapshot& s);
static void assert_valid_metadata_type(Metaspace::MetadataType type) {
assert(type == Metaspace::ClassType || type == Metaspace::NonClassType,
"Invalid metadata type");
}
};
#endif // INCLUDE_NMT
#endif // SHARE_SERVICES_VIRTUALMEMORYTRACKER_HPP

View File

@ -88,3 +88,31 @@ TEST_VM(MetaspaceUtils, non_compressed_class_pointers) {
EXPECT_EQ(reserved_class, 0UL);
}
static void check_metaspace_stats_are_consistent(const MetaspaceStats& stats) {
EXPECT_LT(stats.committed(), stats.reserved());
EXPECT_LT(stats.used(), stats.committed());
}
static void check_metaspace_stats_are_not_null(const MetaspaceStats& stats) {
EXPECT_GT(stats.reserved(), 0UL);
EXPECT_GT(stats.committed(), 0UL);
EXPECT_GT(stats.used(), 0UL);
}
TEST_VM(MetaspaceUtils, get_statistics) {
MetaspaceCombinedStats combined_stats = MetaspaceUtils::get_combined_statistics();
check_metaspace_stats_are_not_null(combined_stats);
check_metaspace_stats_are_consistent(combined_stats);
check_metaspace_stats_are_not_null(combined_stats.non_class_space_stats());
check_metaspace_stats_are_consistent(combined_stats.non_class_space_stats());
if (UseCompressedClassPointers) {
check_metaspace_stats_are_not_null(combined_stats.class_space_stats());
check_metaspace_stats_are_consistent(combined_stats.class_space_stats());
} else {
// if we don't have a class space, combined stats should equal non-class stats
EXPECT_EQ(combined_stats.non_class_space_stats().reserved(), combined_stats.reserved());
EXPECT_EQ(combined_stats.non_class_space_stats().committed(), combined_stats.committed());
EXPECT_EQ(combined_stats.non_class_space_stats().used(), combined_stats.used());
}
}