mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-28 16:50:10 +00:00
239 lines
7.3 KiB
C++
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
|
|
|