src/share/vm/memory/metaspace.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/memory/metaspace.cpp
src/share/vm/memory/metaspace.cpp
Print this page
*** 613,624 ****
// are done from the current chunk. The list is used for deallocating
// chunks when the SpaceManager is freed.
Metachunk* _chunks_in_use[NumberOfInUseLists];
Metachunk* _current_chunk;
! // Number of small chunks to allocate to a manager
! // If class space manager, small chunks are unlimited
static uint const _small_chunk_limit;
// Sum of all space in allocated chunks
size_t _allocated_blocks_words;
--- 613,623 ----
// are done from the current chunk. The list is used for deallocating
// chunks when the SpaceManager is freed.
Metachunk* _chunks_in_use[NumberOfInUseLists];
Metachunk* _current_chunk;
! // Maximum number of small chunks to allocate to a SpaceManager
static uint const _small_chunk_limit;
// Sum of all space in allocated chunks
size_t _allocated_blocks_words;
*** 729,738 ****
--- 728,739 ----
Metachunk* get_new_chunk(size_t word_size, size_t grow_chunks_by_words);
// Block allocation and deallocation.
// Allocates a block from the current chunk
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
MetaWord* allocate_work(size_t word_size);
// Returns a block to the per manager freelist
*** 2010,2022 ****
}
size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to
! // _small_chunk_limit small chunks can be allocated but
! // once a medium chunk has been allocated, no more small
! // chunks will be allocated.
size_t chunk_word_size;
if (chunks_in_use(MediumIndex) == NULL &&
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
chunk_word_size = (size_t) small_chunk_size();
if (word_size + Metachunk::overhead() > small_chunk_size()) {
--- 2011,2022 ----
}
size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to
! // _small_chunk_limit small chunks can be allocated.
! // After that a medium chunk is preferred.
size_t chunk_word_size;
if (chunks_in_use(MediumIndex) == NULL &&
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
chunk_word_size = (size_t) small_chunk_size();
if (word_size + Metachunk::overhead() > small_chunk_size()) {
*** 2080,2090 ****
" words " SIZE_FORMAT " words used " SIZE_FORMAT
" words left",
word_size, words_used, words_left);
}
! // Get another chunk out of the virtual space
size_t grow_chunks_by_words = calc_chunk_size(word_size);
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
MetaWord* mem = NULL;
--- 2080,2090 ----
" words " SIZE_FORMAT " words used " SIZE_FORMAT
" words left",
word_size, words_used, words_left);
}
! // Get another chunk
size_t grow_chunks_by_words = calc_chunk_size(word_size);
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
MetaWord* mem = NULL;
*** 2411,2420 ****
--- 2411,2457 ----
}
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) {
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
size_t raw_word_size = get_raw_word_size(word_size);
BlockFreelist* fl = block_freelists();
*** 3559,3570 ****
--- 3596,3618 ----
loader_data, word_size, mdtype);
}
}
if (result == 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.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
return result;
src/share/vm/memory/metaspace.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File