# HG changeset patch # User tonyp # Date 1303242419 14400 # Node ID 640f1a6f0b85b337725159cd1d4d486f257b64df # Parent 7e9f22667cfcf03f1f92448282bd2f1917dacdb9 7011855: G1: non-product flag to artificially grow the heap Summary: It introduces non-product cmd line parameter G1DummyRegionsPerGC which indicates how many "dummy" regions to allocate at the end of each GC. This allows the G1 heap to grow artificially and makes concurrent marking cycles more frequent irrespective of what the application that is running is doing. The dummy regions will be found totally empty during cleanup so this parameter can also be used to stress the concurrent cleanup operation. Reviewed-by: brutisso, johnc diff -r 7e9f22667cfc -r 640f1a6f0b85 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Apr 18 16:27:16 2011 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Apr 19 15:46:59 2011 -0400 @@ -2113,6 +2113,28 @@ (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); } +#ifndef PRODUCT +void G1CollectedHeap::allocate_dummy_regions() { + // Let's fill up most of the region + size_t word_size = HeapRegion::GrainWords - 1024; + // And as a result the region we'll allocate will be humongous. + guarantee(isHumongous(word_size), "sanity"); + + for (uintx i = 0; i < G1DummyRegionsPerGC; ++i) { + // Let's use the existing mechanism for the allocation + HeapWord* dummy_obj = humongous_obj_allocate(word_size); + if (dummy_obj != NULL) { + MemRegion mr(dummy_obj, word_size); + CollectedHeap::fill_with_object(mr); + } else { + // If we can't allocate once, we probably cannot allocate + // again. Let's get out of the loop. + break; + } + } +} +#endif // !PRODUCT + void G1CollectedHeap::increment_full_collections_completed(bool concurrent) { MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); @@ -3338,6 +3360,8 @@ doConcurrentMark(); } + allocate_dummy_regions(); + #if YOUNG_LIST_VERBOSE gclog_or_tty->print_cr("\nEnd of the pause.\nYoung_list:"); _young_list->print(); diff -r 7e9f22667cfc -r 640f1a6f0b85 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Apr 18 16:27:16 2011 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Apr 19 15:46:59 2011 -0400 @@ -298,6 +298,14 @@ // started is maintained in _total_full_collections in CollectedHeap. volatile unsigned int _full_collections_completed; + // This is a non-product method that is helpful for testing. It is + // called at the end of a GC and artificially expands the heap by + // allocating a number of dead regions. This way we can induce very + // frequent marking cycles and stress the cleanup / concurrent + // cleanup code more (as all the regions that will be allocated by + // this method will be found dead by the marking cycle). + void allocate_dummy_regions() PRODUCT_RETURN; + // These are macros so that, if the assert fires, we get the correct // line number, file, etc. diff -r 7e9f22667cfc -r 640f1a6f0b85 hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Mon Apr 18 16:27:16 2011 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Apr 19 15:46:59 2011 -0400 @@ -300,6 +300,11 @@ develop(uintx, G1StressConcRegionFreeingDelayMillis, 0, \ "Artificial delay during concurrent region freeing") \ \ + develop(uintx, G1DummyRegionsPerGC, 0, \ + "The number of dummy regions G1 will allocate at the end of " \ + "each evacuation pause in order to artificially fill up the " \ + "heap and stress the marking implementation.") \ + \ develop(bool, ReduceInitialCardMarksForG1, false, \ "When ReduceInitialCardMarks is true, this flag setting " \ " controls whether G1 allows the RICM optimization") \