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