< prev index next >

src/share/vm/gc/cms/parNewGeneration.cpp

Print this page
rev 8461 : 8086056: ParNew: auto-tune ParGCCardsPerStrideChunk
Summary: Automatically calculate ParGCCardsPerStrideChunk based on the old gen capacity.
Reviewed-by:
rev 8441 : 8081007: Remove redundant active worker variables and calls in ParNewGeneration::collect
Reviewed-by: pliden, kbarrett, ehelin
rev 8409 : 8080879: Remove FlexibleWorkGang::set_for_termination
Reviewed-by: brutisso, kbarrett, pliden
rev 8404 : 8080876: Replace unnecessary MAX2(ParallelGCThreads, 1) calls with ParallelGCThreads
Reviewed-by: kbarrett, mgerdin
rev 8399 : 8080113: Remove CollectedHeap::set_par_threads()
Reviewed-by: jmasa, kbarrett
rev 8397 : 8080111: Remove SubTaskDone::_n_threads
Reviewed-by: jmasa, kbarrett
rev 8396 : 8080110: Remove usage of CollectedHeap::n_par_threads() from root processing
Reviewed-by: jmasa, kbarrett
rev 8362 : 8079792: GC directory structure cleanup
Reviewed-by: brutisso, stefank, david

@@ -618,11 +618,12 @@
 ParNewGeneration::
 ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level)
   : 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;)
   _task_queues = new ObjToScanQueueSet(ParallelGCThreads);
   guarantee(_task_queues != NULL, "task_queues allocation failure.");

@@ -656,10 +657,14 @@
     const char* cname =
          PerfDataManager::counter_name(_gen_counters->name_space(), "threads");
     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 )
 #endif
 

@@ -878,10 +883,46 @@
   }
   // Reset the PromotionFailureALot counters.
   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,
                                bool   is_tlab) {
   assert(full || size > 0, "otherwise we don't want to collect");

@@ -923,10 +964,11 @@
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
   age_table()->clear();
   to()->clear(SpaceDecorator::Mangle);
+  adjust_cards_per_stride(*_old_gen);
 
   gch->save_marks();
 
   // Set the correct parallelism (number of queues) in the reference processor
   ref_processor()->set_active_mt_degree(active_workers);
< prev index next >