8307958: Metaspace verification is slow causing extreme class unloading times

Reviewed-by: stuefe, coleenp
This commit is contained in:
Axel Boldt-Christmas 2023-05-25 09:03:30 +00:00
parent d87713440a
commit 8d8153e98a
6 changed files with 35 additions and 34 deletions

View File

@ -49,7 +49,7 @@ namespace metaspace {
// Return a single chunk to the freelist and adjust accounting. No merge is attempted.
void ChunkManager::return_chunk_simple_locked(Metachunk* c) {
assert_lock_strong(Metaspace_lock);
DEBUG_ONLY(c->verify());
SOMETIMES(c->verify();)
_chunks.add(c);
c->reset_used_words();
// Tracing
@ -82,7 +82,7 @@ void ChunkManager::split_chunk_and_add_splinters(Metachunk* c, chunklevel_t targ
assert(c->prev() == nullptr && c->next() == nullptr, "Chunk must be outside of any list.");
DEBUG_ONLY(chunklevel::check_valid_level(target_level);)
DEBUG_ONLY(c->verify();)
SOMETIMES(c->verify();)
UL2(debug, "splitting chunk " METACHUNK_FORMAT " to " CHKLVL_FORMAT ".",
METACHUNK_FORMAT_ARGS(c), target_level);
@ -101,8 +101,8 @@ void ChunkManager::split_chunk_and_add_splinters(Metachunk* c, chunklevel_t targ
} else {
assert(c->committed_words() == committed_words_before, "Sanity");
}
c->verify();
verify_locked();
SOMETIMES(c->verify();)
SOMETIMES(verify_locked();)
SOMETIMES(c->vsnode()->verify_locked();)
#endif
InternalStats::inc_num_chunk_splits();
@ -136,7 +136,7 @@ Metachunk* ChunkManager::get_chunk(chunklevel_t preferred_level, chunklevel_t ma
// This may be either the GC threshold or MaxMetaspaceSize.
Metachunk* ChunkManager::get_chunk_locked(chunklevel_t preferred_level, chunklevel_t max_level, size_t min_committed_words) {
assert_lock_strong(Metaspace_lock);
DEBUG_ONLY(verify_locked();)
SOMETIMES(verify_locked();)
DEBUG_ONLY(chunklevel::check_valid_level(max_level);)
DEBUG_ONLY(chunklevel::check_valid_level(preferred_level);)
@ -255,8 +255,8 @@ void ChunkManager::return_chunk(Metachunk* c) {
void ChunkManager::return_chunk_locked(Metachunk* c) {
assert_lock_strong(Metaspace_lock);
UL2(debug, ": returning chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c));
DEBUG_ONLY(c->verify();)
assert(contains_chunk(c) == false, "A chunk to be added to the freelist must not be in the freelist already.");
SOMETIMES(c->verify();)
ASSERT_SOMETIMES(contains_chunk(c) == false, "A chunk to be added to the freelist must not be in the freelist already.");
assert(c->is_in_use() || c->is_free(), "Unexpected chunk state");
assert(!c->in_list(), "Remove from list first");
@ -272,7 +272,7 @@ void ChunkManager::return_chunk_locked(Metachunk* c) {
if (merged != nullptr) {
InternalStats::inc_num_chunk_merges();
DEBUG_ONLY(merged->verify());
SOMETIMES(merged->verify();)
// We did merge chunks and now have a bigger chunk.
assert(merged->level() < orig_lvl, "Sanity");
UL2(debug, "merged into chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(merged));
@ -280,7 +280,7 @@ void ChunkManager::return_chunk_locked(Metachunk* c) {
}
return_chunk_simple_locked(c);
DEBUG_ONLY(verify_locked();)
SOMETIMES(verify_locked();)
SOMETIMES(c->vsnode()->verify_locked();)
InternalStats::inc_num_chunks_returned_to_freelist();
}
@ -373,8 +373,8 @@ void ChunkManager::purge() {
ls.cr();
}
}
DEBUG_ONLY(_vslist->verify_locked());
DEBUG_ONLY(verify_locked());
SOMETIMES(_vslist->verify_locked();)
SOMETIMES(verify_locked();)
}
// Convenience methods to return the global class-space chunkmanager

View File

@ -31,6 +31,7 @@
#include "memory/metaspace/counters.hpp"
#include "memory/metaspace/metachunk.hpp"
#include "memory/metaspace/metachunkList.hpp"
#include "memory/metaspace/metaspaceCommon.hpp"
class outputStream;
@ -102,7 +103,7 @@ public:
// Remove given chunk from anywhere in the list.
Metachunk* remove(Metachunk* c) {
assert(contains(c), "Must be contained here");
ASSERT_SOMETIMES(contains(c), "Must be contained here");
Metachunk* pred = c->prev();
Metachunk* succ = c->next();
if (pred) {
@ -124,7 +125,7 @@ public:
}
void add(Metachunk* c) {
assert(contains(c) == false, "Chunk already in freelist");
ASSERT_SOMETIMES(contains(c) == false, "Chunk already in freelist");
assert(_first == nullptr || _first->level() == c->level(),
"List should only contains chunks of the same level.");
// Uncommitted chunks go to the back, fully or partially committed to the front.

View File

@ -129,9 +129,9 @@ MetaspaceArena::MetaspaceArena(ChunkManager* chunk_manager, const ArenaGrowthPol
MetaspaceArena::~MetaspaceArena() {
#ifdef ASSERT
verify();
SOMETIMES(verify();)
if (Settings::use_allocation_guard()) {
verify_allocation_guards();
SOMETIMES(verify_allocation_guards();)
}
#endif
@ -156,7 +156,7 @@ MetaspaceArena::~MetaspaceArena() {
return_counter.count(), return_counter.total_size());
_total_used_words_counter->decrement_by(return_counter.total_size());
DEBUG_ONLY(chunk_manager()->verify();)
SOMETIMES(chunk_manager()->verify();)
delete _fbl;
UL(debug, ": dies.");
@ -368,7 +368,7 @@ void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
size_t raw_word_size = get_raw_word_size_for_requested_word_size(word_size);
add_allocation_to_fbl(p, raw_word_size);
DEBUG_ONLY(verify_locked();)
SOMETIMES(verify_locked();)
}
// Prematurely returns a metaspace allocation to the _block_freelists because it is not

View File

@ -98,7 +98,7 @@ void RootChunkArea::split(chunklevel_t target_level, Metachunk* c, FreeChunkList
//
DEBUG_ONLY(check_pointer(c->base());)
DEBUG_ONLY(c->verify();)
SOMETIMES(c->verify();)
assert(c->is_free(), "Can only split free chunks.");
DEBUG_ONLY(chunklevel::check_valid_level(target_level));
@ -139,8 +139,8 @@ void RootChunkArea::split(chunklevel_t target_level, Metachunk* c, FreeChunkList
assert(c->level() == target_level, "Sanity");
DEBUG_ONLY(verify();)
DEBUG_ONLY(c->verify();)
SOMETIMES(verify();)
SOMETIMES(c->verify();)
}
// Given a chunk, attempt to merge it recursively with its neighboring chunks.
@ -194,7 +194,7 @@ Metachunk* RootChunkArea::merge(Metachunk* c, FreeChunkListVector* freelists) {
assert(!c->is_root_chunk(), "Cannot be merged further.");
assert(c->is_free(), "Can only merge free chunks.");
DEBUG_ONLY(c->verify();)
SOMETIMES(c->verify();)
log_trace(metaspace)("Attempting to merge chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c));
@ -208,7 +208,7 @@ Metachunk* RootChunkArea::merge(Metachunk* c, FreeChunkListVector* freelists) {
// Note: this is either our buddy or a splinter of the buddy.
Metachunk* const buddy = c->is_leader() ? c->next_in_vs() : c->prev_in_vs();
DEBUG_ONLY(buddy->verify();)
SOMETIMES(buddy->verify();)
// A buddy chunk must be of the same or higher level (so, same size or smaller)
// never be larger.
@ -270,14 +270,14 @@ Metachunk* RootChunkArea::merge(Metachunk* c, FreeChunkListVector* freelists) {
}
result = c = leader;
DEBUG_ONLY(leader->verify();)
SOMETIMES(leader->verify();)
}
} while (!stop);
#ifdef ASSERT
verify();
SOMETIMES(verify();)
if (result != nullptr) {
result->verify();
SOMETIMES(result->verify();)
}
#endif // ASSERT
return result;
@ -299,7 +299,7 @@ bool RootChunkArea::attempt_enlarge_chunk(Metachunk* c, FreeChunkListVector* fre
// There is no real reason for this limitation other than it is not
// needed on free chunks since they should be merged already:
assert(c->is_in_use(), "Can only enlarge in use chunks.");
DEBUG_ONLY(c->verify();)
SOMETIMES(c->verify();)
if (!c->is_leader()) {
return false;
@ -307,7 +307,7 @@ bool RootChunkArea::attempt_enlarge_chunk(Metachunk* c, FreeChunkListVector* fre
// We are the leader, so the buddy must follow us.
Metachunk* const buddy = c->next_in_vs();
DEBUG_ONLY(buddy->verify();)
SOMETIMES(buddy->verify();)
// Of course buddy cannot be larger than us.
assert(buddy->level() >= c->level(), "Sanity");
@ -352,7 +352,7 @@ bool RootChunkArea::attempt_enlarge_chunk(Metachunk* c, FreeChunkListVector* fre
log_debug(metaspace)("Enlarged chunk " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c));
DEBUG_ONLY(verify());
SOMETIMES(verify();)
return true;
}

View File

@ -322,7 +322,7 @@ Metachunk* VirtualSpaceNode::allocate_root_chunk() {
Metachunk* c = rca->alloc_root_chunk_header(this);
assert(c->base() == loc && c->vsnode() == this &&
c->is_free(), "Sanity");
DEBUG_ONLY(c->verify();)
SOMETIMES(c->verify();)
UL2(debug, "new root chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c));
return c;
@ -338,7 +338,7 @@ void VirtualSpaceNode::split(chunklevel_t target_level, Metachunk* c, FreeChunkL
assert_lock_strong(Metaspace_lock);
// Get the area associated with this chunk and let it handle the splitting
RootChunkArea* rca = _root_chunk_area_lut.get_area_by_address(c->base());
DEBUG_ONLY(rca->verify_area_is_ideally_merged();)
SOMETIMES(rca->verify_area_is_ideally_merged();)
rca->split(target_level, c, freelists);
}
@ -358,7 +358,7 @@ Metachunk* VirtualSpaceNode::merge(Metachunk* c, FreeChunkListVector* freelists)
// Get the rca associated with this chunk and let it handle the merging
RootChunkArea* rca = _root_chunk_area_lut.get_area_by_address(c->base());
Metachunk* c2 = rca->merge(c, freelists);
DEBUG_ONLY(rca->verify_area_is_ideally_merged();)
SOMETIMES(rca->verify_area_is_ideally_merged();)
return c2;
}
@ -379,7 +379,7 @@ bool VirtualSpaceNode::attempt_enlarge_chunk(Metachunk* c, FreeChunkListVector*
RootChunkArea* rca = _root_chunk_area_lut.get_area_by_address(c->base());
bool rc = rca->attempt_enlarge_chunk(c, freelists);
DEBUG_ONLY(rca->verify_area_is_ideally_merged();)
SOMETIMES(rca->verify_area_is_ideally_merged();)
if (rc) {
InternalStats::inc_num_chunks_enlarged();
}

View File

@ -37,7 +37,7 @@
* java.xml
* @requires vm.debug
* @requires vm.flagless
* @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockDiagnosticVMOptions -XX:VerifyMetaspaceInterval=3
* @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockDiagnosticVMOptions -XX:VerifyMetaspaceInterval=1
*/
/* @test id=balanced-with-guards
@ -47,7 +47,7 @@
* java.xml
* @requires vm.debug
* @requires vm.flagless
* @run main/native GTestWrapper --gtest_filter=metaspace* -XX:VerifyMetaspaceInterval=3 -XX:+MetaspaceGuardAllocations
* @run main/native GTestWrapper --gtest_filter=metaspace* -XX:VerifyMetaspaceInterval=1 -XX:+MetaspaceGuardAllocations
*/
/* @test id=balanced-no-ccs