提交 0188d1a2 编写于 作者: J jprovino

8081693: metaspace/shrink_grow/CompressedClassSpaceSize fails with OOM: Compressed class space

Summary: metaspace/shrink_grow/CompressedClassSpaceSize fails with OOM: Compressed class space
Reviewed-by: jmasa, kbarrett
上级 4e427252
...@@ -622,8 +622,7 @@ class SpaceManager : public CHeapObj<mtClass> { ...@@ -622,8 +622,7 @@ class SpaceManager : public CHeapObj<mtClass> {
Metachunk* _chunks_in_use[NumberOfInUseLists]; Metachunk* _chunks_in_use[NumberOfInUseLists];
Metachunk* _current_chunk; Metachunk* _current_chunk;
// Number of small chunks to allocate to a manager // Maximum number of small chunks to allocate to a SpaceManager
// If class space manager, small chunks are unlimited
static uint const _small_chunk_limit; static uint const _small_chunk_limit;
// Sum of all space in allocated chunks // Sum of all space in allocated chunks
...@@ -737,6 +736,8 @@ class SpaceManager : public CHeapObj<mtClass> { ...@@ -737,6 +736,8 @@ class SpaceManager : public CHeapObj<mtClass> {
// Block allocation and deallocation. // Block allocation and deallocation.
// Allocates a block from the current chunk // Allocates a block from the current chunk
MetaWord* allocate(size_t word_size); MetaWord* allocate(size_t word_size);
// Allocates a block from a small chunk
MetaWord* get_small_chunk_and_allocate(size_t word_size);
// Helper for allocations // Helper for allocations
MetaWord* allocate_work(size_t word_size); MetaWord* allocate_work(size_t word_size);
...@@ -2031,9 +2032,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { ...@@ -2031,9 +2032,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
size_t SpaceManager::calc_chunk_size(size_t word_size) { size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to // Decide between a small chunk and a medium chunk. Up to
// _small_chunk_limit small chunks can be allocated but // _small_chunk_limit small chunks can be allocated.
// once a medium chunk has been allocated, no more small // After that a medium chunk is preferred.
// chunks will be allocated.
size_t chunk_word_size; size_t chunk_word_size;
if (chunks_in_use(MediumIndex) == NULL && if (chunks_in_use(MediumIndex) == NULL &&
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
...@@ -2101,7 +2101,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) { ...@@ -2101,7 +2101,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
word_size, words_used, words_left); word_size, words_used, words_left);
} }
// Get another chunk out of the virtual space // Get another chunk
size_t grow_chunks_by_words = calc_chunk_size(word_size); size_t grow_chunks_by_words = calc_chunk_size(word_size);
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words); Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
...@@ -2432,6 +2432,43 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size, ...@@ -2432,6 +2432,43 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size,
return next; return next;
} }
/*
* The policy is to allocate up to _small_chunk_limit small chunks
* after which only medium chunks are allocated. This is done to
* reduce fragmentation. In some cases, this can result in a lot
* of small chunks being allocated to the point where it's not
* possible to expand. If this happens, there may be no medium chunks
* available and OOME would be thrown. Instead of doing that,
* if the allocation request size fits in a small chunk, an attempt
* will be made to allocate a small chunk.
*/
MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
if (word_size + Metachunk::overhead() > small_chunk_size()) {
return NULL;
}
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
MetaWord* mem = NULL;
if (chunk != NULL) {
// Add chunk to the in-use chunk list and do an allocation from it.
// Add to this manager's list of chunks in use.
add_chunk(chunk, false);
mem = chunk->allocate(word_size);
inc_used_metrics(word_size);
// Track metaspace memory usage statistic.
track_metaspace_memory_usage();
}
return mem;
}
MetaWord* SpaceManager::allocate(size_t word_size) { MetaWord* SpaceManager::allocate(size_t word_size) {
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
...@@ -3511,7 +3548,18 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, ...@@ -3511,7 +3548,18 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
} }
if (result == NULL) { if (result == NULL) {
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL); SpaceManager* sm;
if (is_class_space_allocation(mdtype)) {
sm = loader_data->metaspace_non_null()->class_vsm();
} else {
sm = loader_data->metaspace_non_null()->vsm();
}
result = sm->get_small_chunk_and_allocate(word_size);
if (result == NULL) {
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
}
} }
// Zero initialize. // Zero initialize.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册