src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/memory/metaspace.cpp	Sat May 16 14:36:37 2015
--- new/src/share/vm/memory/metaspace.cpp	Sat May 16 14:36:36 2015

*** 613,624 **** --- 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; // Number of small chunks to allocate to a manager // If class space manager, small chunks are unlimited + // 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;
*** 2010,2022 **** --- 2009,2020 ---- } 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. ! // _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()) {
*** 2059,2068 **** --- 2057,2076 ---- } MemoryService::track_metaspace_memory_usage(); } } + /* + * 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::grow_and_allocate(size_t word_size) { assert(vs_list()->current_virtual_space() != NULL, "Should have been set"); assert(current_chunk() == NULL || current_chunk()->allocate(word_size) == NULL,
*** 2080,2095 **** --- 2088,2113 ---- " 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; + if (next == NULL && + word_size + Metachunk::overhead() <= small_chunk_size() && + grow_chunks_by_words == medium_chunk_size()) { + /* + * There are no medium chunks available but a small chunk is big enough. + * See if a small chunk is available. + */ + next = get_new_chunk(word_size, small_chunk_size()); + } + // If a chunk was available, add it to the in-use chunk list // and do an allocation from it. if (next != NULL) { // Add to this manager's list of chunks in use. add_chunk(next, false);

src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File