# HG changeset patch # User tonyp # Date 1434579792 14400 # Wed Jun 17 18:23:12 2015 -0400 # Node ID c6fa0403b66916939ecc63e2464c455487939041 # Parent 41e47efcd333a7b2e837a23d5f531953c167d861 8086056: ParNew: auto-tune ParGCCardsPerStrideChunk Summary: Automatically calculate ParGCCardsPerStrideChunk based on the old gen capacity. Reviewed-by: diff --git a/src/share/vm/gc/cms/parNewGeneration.cpp b/src/share/vm/gc/cms/parNewGeneration.cpp --- a/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/src/share/vm/gc/cms/parNewGeneration.cpp @@ -620,7 +620,8 @@ : DefNewGeneration(rs, initial_byte_size, level, "PCopy"), _overflow_list(NULL), _is_alive_closure(this), - _plab_stats(YoungPLABSize, PLABWeight) + _plab_stats(YoungPLABSize, PLABWeight), + _should_adjust_cards_per_stride(false) { NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) NOT_PRODUCT(_num_par_pushes = 0;) @@ -658,6 +659,10 @@ PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None, ParallelGCThreads, CHECK); } + + // we'll automatically calculate ParGCCardsPerStrideChunk if it has + // not been explicitly set on the command line + _should_adjust_cards_per_stride = FLAG_IS_DEFAULT(ParGCCardsPerStrideChunk); } #ifdef _MSC_VER #pragma warning( pop ) @@ -880,6 +885,42 @@ NOT_PRODUCT(gch->reset_promotion_should_fail();) } +void ParNewGeneration::adjust_cards_per_stride(const Generation& old_gen) { + if (!_should_adjust_cards_per_stride) return; + + const size_t MinOldGenCapacity = G; + const size_t MaxOldGenCapacity = 16 * G; + assert(MinOldGenCapacity <= MaxOldGenCapacity, "sanity"); + const size_t OldGenCapacityDiff = MaxOldGenCapacity - MinOldGenCapacity; + + const intx MinStrideChunkSize = 256; + const intx MaxStrideChunkSize = 8 * K; + assert(MinStrideChunkSize <= MaxStrideChunkSize, "sanity"); + const intx StrideChunkSizeDiff = MaxStrideChunkSize - MinStrideChunkSize; + + const size_t capacity = old_gen.capacity(); + // adj_capacity = capacity bounded by {Min,Max}OldGenCapacity + size_t adj_capacity = capacity; + adj_capacity = MAX2(adj_capacity, MinOldGenCapacity); + adj_capacity = MIN2(adj_capacity, MaxOldGenCapacity); + + const size_t capacity_offset = adj_capacity - MinOldGenCapacity; + assert(capacity_offset && capacity_offset <= OldGenCapacityDiff, + "sanity"); + const double r = (double) capacity_offset / (double) OldGenCapacityDiff; + const intx stride_chunk_offset = (intx) (r * (double) StrideChunkSizeDiff); + const int stride_chunk_size_log = + log2_intptr((intptr_t) (MinStrideChunkSize + stride_chunk_offset)); + const intx stride_chunk_size = (intx) 1 << stride_chunk_size_log; + + assert(MinStrideChunkSize <= stride_chunk_size && + stride_chunk_size <= MaxStrideChunkSize && + is_power_of_2((intptr_t) stride_chunk_size), + err_msg("stride_chunk_size: "INTX_FORMAT, stride_chunk_size)); + + FLAG_SET_ERGO(intx, ParGCCardsPerStrideChunk, stride_chunk_size); +} + void ParNewGeneration::collect(bool full, bool clear_all_soft_refs, size_t size, @@ -925,6 +966,7 @@ age_table()->clear(); to()->clear(SpaceDecorator::Mangle); + adjust_cards_per_stride(*_old_gen); gch->save_marks(); diff --git a/src/share/vm/gc/cms/parNewGeneration.hpp b/src/share/vm/gc/cms/parNewGeneration.hpp --- a/src/share/vm/gc/cms/parNewGeneration.hpp +++ b/src/share/vm/gc/cms/parNewGeneration.hpp @@ -345,13 +345,19 @@ void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set); - protected: - bool _survivor_overflow; bool survivor_overflow() { return _survivor_overflow; } void set_survivor_overflow(bool v) { _survivor_overflow = v; } + // true -> should automatically calculate ParGCCardsPerStrideChunk + // before each young GC + bool _should_adjust_cards_per_stride; + + // automatically calculate ParGCCardsPerStrideChunk based on the old + // gen capacity before each young GC + void adjust_cards_per_stride(const Generation& old_gen); + public: ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level);