jdk/src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp
Thomas Stuefe da296cbea1 8363996: Obsolete UseCompressedClassPointers
Reviewed-by: rkennke, kvn, adinn, dholmes, mdoerr, iklam, fyang
2026-03-26 11:08:48 +00:00

239 lines
7.3 KiB
C++

/*
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020 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.
*
*/
#include "memory/metaspace/metaspaceCommon.hpp"
#include "memory/metaspace/metaspaceStatistics.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
namespace metaspace {
// Returns total word size of all chunks in this manager.
void ChunkManagerStats::add(const ChunkManagerStats& other) {
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
_num_chunks[l] += other._num_chunks[l];
_committed_word_size[l] += other._committed_word_size[l];
}
}
// Returns total word size of all chunks in this manager.
size_t ChunkManagerStats::total_word_size() const {
size_t s = 0;
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
s += _num_chunks[l] * chunklevel::word_size_for_level(l);
}
return s;
}
// Returns total committed word size of all chunks in this manager.
size_t ChunkManagerStats::total_committed_word_size() const {
size_t s = 0;
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
s += _committed_word_size[l];
}
return s;
}
void ChunkManagerStats::print_on(outputStream* st, size_t scale) const {
// Note: used as part of MetaspaceReport so formatting matters.
size_t total_size = 0;
size_t total_committed_size = 0;
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
st->cr();
chunklevel::print_chunk_size(st, l);
st->print(": ");
if (_num_chunks[l] > 0) {
const size_t word_size = _num_chunks[l] * chunklevel::word_size_for_level(l);
st->print("%4d, capacity=", _num_chunks[l]);
print_scaled_words(st, word_size, scale);
st->print(", committed=");
print_scaled_words_and_percentage(st, _committed_word_size[l], word_size, scale);
total_size += word_size;
total_committed_size += _committed_word_size[l];
} else {
st->print("(none)");
}
}
st->cr();
st->print("Total word size: ");
print_scaled_words(st, total_size, scale);
st->print(", committed: ");
print_scaled_words_and_percentage(st, total_committed_size, total_size, scale);
st->cr();
}
#ifdef ASSERT
void ChunkManagerStats::verify() const {
assert(total_committed_word_size() <= total_word_size(),
"Sanity");
}
#endif
void InUseChunkStats::print_on(outputStream* st, size_t scale) const {
int col = st->position();
st->print("%4d chunk%s, ", _num, _num != 1 ? "s" : "");
if (_num > 0) {
col += 14; st->fill_to(col);
print_scaled_words(st, _word_size, scale, 5);
st->print(" capacity,");
col += 20; st->fill_to(col);
print_scaled_words_and_percentage(st, _committed_words, _word_size, scale, 5);
st->print(" committed, ");
col += 18; st->fill_to(col);
print_scaled_words_and_percentage(st, _used_words, _word_size, scale, 5);
st->print(" used, ");
col += 20; st->fill_to(col);
print_scaled_words_and_percentage(st, _free_words, _word_size, scale, 5);
st->print(" free, ");
col += 20; st->fill_to(col);
print_scaled_words_and_percentage(st, _waste_words, _word_size, scale, 5);
st->print(" waste ");
}
}
#ifdef ASSERT
void InUseChunkStats::verify() const {
assert(_word_size >= _committed_words &&
_committed_words == _used_words + _free_words + _waste_words,
"Sanity: cap %zu, committed %zu, used %zu, free %zu, waste %zu.",
_word_size, _committed_words, _used_words, _free_words, _waste_words);
}
#endif
void ArenaStats::add(const ArenaStats& other) {
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
_stats[l].add(other._stats[l]);
}
_free_blocks_num += other._free_blocks_num;
_free_blocks_word_size += other._free_blocks_word_size;
}
// Returns total chunk statistics over all chunk types.
InUseChunkStats ArenaStats::totals() const {
InUseChunkStats out;
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
out.add(_stats[l]);
}
return out;
}
void ArenaStats::print_on(outputStream* st, size_t scale, bool detailed) const {
if (detailed) {
StreamIndentor si(st, 2);
st->cr();
st->print("Usage by chunk level:");
{
StreamIndentor si2(st, 2);
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
st->cr();
chunklevel::print_chunk_size(st, l);
st->print(" chunks: ");
if (_stats[l]._num == 0) {
st->print(" (none)");
} else {
_stats[l].print_on(st, scale);
}
}
st->cr();
st->print("%15s: ", "-total-");
totals().print_on(st, scale);
}
if (_free_blocks_num > 0) {
st->cr();
st->print("deallocated: %zu blocks with ", _free_blocks_num);
print_scaled_words(st, _free_blocks_word_size, scale);
}
} else {
totals().print_on(st, scale);
st->print(", ");
st->print("deallocated: %zu blocks with ", _free_blocks_num);
print_scaled_words(st, _free_blocks_word_size, scale);
}
}
#ifdef ASSERT
void ArenaStats::verify() const {
size_t total_used = 0;
for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) {
_stats[l].verify();
total_used += _stats[l]._used_words;
}
}
#endif
// Returns total arena statistics for both class and non-class metaspace
ArenaStats ClmsStats::totals() const {
ArenaStats out;
out.add(_arena_stats_nonclass);
out.add(_arena_stats_class);
return out;
}
void ClmsStats::print_on(outputStream* st, size_t scale, bool detailed) const {
StreamIndentor si(st, 2);
st->cr();
CLASS_SPACE_ONLY(st->print("Non-Class: ");)
_arena_stats_nonclass.print_on(st, scale, detailed);
if (detailed) {
st->cr();
}
#if INCLUDE_CLASS_SPACE
st->cr();
st->print(" Class: ");
_arena_stats_class.print_on(st, scale, detailed);
if (detailed) {
st->cr();
}
st->cr();
st->print(" Both: ");
totals().print_on(st, scale, detailed);
if (detailed) {
st->cr();
}
#endif // INCLUDE_CLASS_SPACE
st->cr();
}
#ifdef ASSERT
void ClmsStats::verify() const {
_arena_stats_nonclass.verify();
_arena_stats_class.verify();
}
#endif
} // end namespace metaspace