mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8009561: NPG: Metaspace fragmentation when retiring a Metachunk
Use best-fit block-splitting freelist allocation from the block freelist. Reviewed-by: jmasa, stefank
This commit is contained in:
parent
86624d96d7
commit
1d97871624
1 changed files with 32 additions and 3 deletions
|
@ -51,7 +51,7 @@ const bool metaspace_slow_verify = false;
|
||||||
// Parameters for stress mode testing
|
// Parameters for stress mode testing
|
||||||
const uint metadata_deallocate_a_lot_block = 10;
|
const uint metadata_deallocate_a_lot_block = 10;
|
||||||
const uint metadata_deallocate_a_lock_chunk = 3;
|
const uint metadata_deallocate_a_lock_chunk = 3;
|
||||||
size_t const allocation_from_dictionary_limit = 64 * K;
|
size_t const allocation_from_dictionary_limit = 4 * K;
|
||||||
|
|
||||||
MetaWord* last_allocated = 0;
|
MetaWord* last_allocated = 0;
|
||||||
|
|
||||||
|
@ -228,6 +228,10 @@ class BlockFreelist VALUE_OBJ_CLASS_SPEC {
|
||||||
BlockTreeDictionary* _dictionary;
|
BlockTreeDictionary* _dictionary;
|
||||||
static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size);
|
static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size);
|
||||||
|
|
||||||
|
// Only allocate and split from freelist if the size of the allocation
|
||||||
|
// is at least 1/4th the size of the available block.
|
||||||
|
const static int WasteMultiplier = 4;
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
BlockTreeDictionary* dictionary() const { return _dictionary; }
|
BlockTreeDictionary* dictionary() const { return _dictionary; }
|
||||||
|
|
||||||
|
@ -623,6 +627,7 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||||
|
|
||||||
// Add chunk to the list of chunks in use
|
// Add chunk to the list of chunks in use
|
||||||
void add_chunk(Metachunk* v, bool make_current);
|
void add_chunk(Metachunk* v, bool make_current);
|
||||||
|
void retire_current_chunk();
|
||||||
|
|
||||||
Mutex* lock() const { return _lock; }
|
Mutex* lock() const { return _lock; }
|
||||||
|
|
||||||
|
@ -807,12 +812,25 @@ MetaWord* BlockFreelist::get_block(size_t word_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Metablock* free_block =
|
Metablock* free_block =
|
||||||
dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::exactly);
|
dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::atLeast);
|
||||||
if (free_block == NULL) {
|
if (free_block == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (MetaWord*) free_block;
|
const size_t block_size = free_block->size();
|
||||||
|
if (block_size > WasteMultiplier * word_size) {
|
||||||
|
return_block((MetaWord*)free_block, block_size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaWord* new_block = (MetaWord*)free_block;
|
||||||
|
assert(block_size >= word_size, "Incorrect size of block from freelist");
|
||||||
|
const size_t unused = block_size - word_size;
|
||||||
|
if (unused >= TreeChunk<Metablock, FreeList>::min_size()) {
|
||||||
|
return_block(new_block + word_size, unused);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFreelist::print_on(outputStream* st) const {
|
void BlockFreelist::print_on(outputStream* st) const {
|
||||||
|
@ -2278,6 +2296,7 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
|
||||||
ChunkIndex index = ChunkManager::list_index(new_chunk->word_size());
|
ChunkIndex index = ChunkManager::list_index(new_chunk->word_size());
|
||||||
|
|
||||||
if (index != HumongousIndex) {
|
if (index != HumongousIndex) {
|
||||||
|
retire_current_chunk();
|
||||||
set_current_chunk(new_chunk);
|
set_current_chunk(new_chunk);
|
||||||
new_chunk->set_next(chunks_in_use(index));
|
new_chunk->set_next(chunks_in_use(index));
|
||||||
set_chunks_in_use(index, new_chunk);
|
set_chunks_in_use(index, new_chunk);
|
||||||
|
@ -2313,6 +2332,16 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpaceManager::retire_current_chunk() {
|
||||||
|
if (current_chunk() != NULL) {
|
||||||
|
size_t remaining_words = current_chunk()->free_word_size();
|
||||||
|
if (remaining_words >= TreeChunk<Metablock, FreeList>::min_size()) {
|
||||||
|
block_freelists()->return_block(current_chunk()->allocate(remaining_words), remaining_words);
|
||||||
|
inc_used_metrics(remaining_words);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Metachunk* SpaceManager::get_new_chunk(size_t word_size,
|
Metachunk* SpaceManager::get_new_chunk(size_t word_size,
|
||||||
size_t grow_chunks_by_words) {
|
size_t grow_chunks_by_words) {
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue