# HG changeset patch # User brutisso # Date 1315492181 -7200 # Node ID af2ab04e0038507e9211dad6883806c0676e49cf # Parent 4f41766176cfe3a1486c5d64dc88f5fb035a523c 6929868: G1: introduce min / max young gen size bounds Summary: Make G1 handle young gen size command line flags more consistently Reviewed-by: tonyp, jwilhelm diff -r 4f41766176cf -r af2ab04e0038 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Sep 08 05:16:49 2011 -0400 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Sep 08 16:29:41 2011 +0200 @@ -1682,7 +1682,7 @@ } assert(curr == mr.end(), "post-condition"); } - g1_policy()->calculate_reserve(n_regions()); + g1_policy()->record_new_heap_size(n_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not expand the heap", @@ -1733,7 +1733,7 @@ _expansion_regions += num_regions_deleted; update_committed_space(old_end, new_end); HeapRegionRemSet::shrink_heap(n_regions()); - g1_policy()->calculate_reserve(n_regions()); + g1_policy()->record_new_heap_size(n_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not shrink the heap", @@ -3525,6 +3525,19 @@ init_mutator_alloc_region(); + { + size_t expand_bytes = g1_policy()->expansion_amount(); + if (expand_bytes > 0) { + size_t bytes_before = capacity(); + if (!expand(expand_bytes)) { + // We failed to expand the heap so let's verify that + // committed/uncommitted amount match the backing store + assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); + assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + } + } + } + double end_time_sec = os::elapsedTime(); double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; g1_policy()->record_pause_time_ms(pause_time_ms); diff -r 4f41766176cf -r af2ab04e0038 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Sep 08 05:16:49 2011 -0400 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Sep 08 16:29:41 2011 +0200 @@ -146,6 +146,7 @@ _stop_world_start(0.0), _all_stop_world_times_ms(new NumberSeq()), _all_yield_times_ms(new NumberSeq()), + _using_new_ratio_calculations(false), _all_mod_union_times_ms(new NumberSeq()), @@ -430,7 +431,7 @@ "it's been updated to %u", reserve_perc); } _reserve_factor = (double) reserve_perc / 100.0; - // This will be set in calculate_reserve() when the heap is expanded + // This will be set when the heap is expanded // for the first time during initialization. _reserve_regions = 0; @@ -458,16 +459,15 @@ // ParallelScavengeHeap::initialize()). We might change this in the // future, but it's a good start. class G1YoungGenSizer : public TwoGenerationCollectorPolicy { - size_t size_to_region_num(size_t byte_size) { - return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); - } public: G1YoungGenSizer() { initialize_flags(); initialize_size_info(); } - + size_t size_to_region_num(size_t byte_size) { + return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); + } size_t min_young_region_num() { return size_to_region_num(_min_gen0_size); } @@ -479,6 +479,13 @@ } }; +void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) { + assert(number_of_heap_regions > 0, "Heap must be initialized"); + size_t young_size = number_of_heap_regions / (NewRatio + 1); + _min_desired_young_length = young_size; + _max_desired_young_length = young_size; +} + void G1CollectorPolicy::init() { // Set aside an initial future to_space. _g1 = G1CollectedHeap::heap(); @@ -489,16 +496,35 @@ G1YoungGenSizer sizer; size_t initial_region_num = sizer.initial_young_region_num(); - - if (UseAdaptiveSizePolicy) { - set_adaptive_young_list_length(true); + _min_desired_young_length = sizer.min_young_region_num(); + _max_desired_young_length = sizer.max_young_region_num(); + + if (FLAG_IS_CMDLINE(NewRatio)) { + if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { + gclog_or_tty->print_cr("-XX:NewSize and -XX:MaxNewSize overrides -XX:NewRatio"); + } else { + // Treat NewRatio as a fixed size that is only recalculated when the heap size changes + size_t heap_regions = sizer.size_to_region_num(_g1->n_regions()); + update_young_list_size_using_newratio(heap_regions); + _using_new_ratio_calculations = true; + } + } + + // GenCollectorPolicy guarantees that min <= initial <= max. + // Asserting here just to state that we rely on this property. + assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); + assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large"); + assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small"); + + set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length); + if (adaptive_young_list_length()) { _young_list_fixed_length = 0; } else { - set_adaptive_young_list_length(false); _young_list_fixed_length = initial_region_num; } _free_regions_at_end_of_collection = _g1->free_regions(); update_young_list_target_length(); + _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes; // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info @@ -541,11 +567,18 @@ return true; } -void G1CollectorPolicy::calculate_reserve(size_t all_regions) { - double reserve_regions_d = (double) all_regions * _reserve_factor; +void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) { + // re-calculate the necessary reserve + double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; // We use ceiling so that if reserve_regions_d is > 0.0 (but // smaller than 1.0) we'll get 1. _reserve_regions = (size_t) ceil(reserve_regions_d); + + if (_using_new_ratio_calculations) { + // -XX:NewRatio was specified so we need to update the + // young gen length when the heap size has changed. + update_young_list_size_using_newratio(new_number_of_regions); + } } size_t G1CollectorPolicy::calculate_young_list_desired_min_length( @@ -561,16 +594,16 @@ // otherwise we don't have enough info to make the prediction } } - // Here, we might want to also take into account any additional - // constraints (i.e., user-defined minimum bound). Currently, we don't. - return base_min_length + desired_min_length; + desired_min_length += base_min_length; + // make sure we don't go below any user-defined minimum bound + return MAX2(_min_desired_young_length, desired_min_length); } size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { // Here, we might want to also take into account any additional // constraints (i.e., user-defined minimum bound). Currently, we // effectively don't set this bound. - return _g1->n_regions(); + return _max_desired_young_length; } void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { @@ -1699,20 +1732,26 @@ size_t used_before_gc = _cur_collection_pause_used_at_start_bytes; size_t used = _g1->used(); size_t capacity = _g1->capacity(); + size_t eden_capacity = + (_young_list_target_length * HeapRegion::GrainBytes) - survivor_bytes; gclog_or_tty->print_cr( - " [Eden: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " - "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " - "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" - EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", - EXT_SIZE_PARAMS(_eden_bytes_before_gc), - EXT_SIZE_PARAMS(eden_bytes), - EXT_SIZE_PARAMS(_survivor_bytes_before_gc), - EXT_SIZE_PARAMS(survivor_bytes), - EXT_SIZE_PARAMS(used_before_gc), - EXT_SIZE_PARAMS(_capacity_before_gc), - EXT_SIZE_PARAMS(used), - EXT_SIZE_PARAMS(capacity)); + " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") " + "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " + "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" + EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", + EXT_SIZE_PARAMS(_eden_bytes_before_gc), + EXT_SIZE_PARAMS(_prev_eden_capacity), + EXT_SIZE_PARAMS(eden_bytes), + EXT_SIZE_PARAMS(eden_capacity), + EXT_SIZE_PARAMS(_survivor_bytes_before_gc), + EXT_SIZE_PARAMS(survivor_bytes), + EXT_SIZE_PARAMS(used_before_gc), + EXT_SIZE_PARAMS(_capacity_before_gc), + EXT_SIZE_PARAMS(used), + EXT_SIZE_PARAMS(capacity)); + + _prev_eden_capacity = eden_capacity; } else if (PrintGC) { _g1->print_size_transition(gclog_or_tty, _cur_collection_pause_used_at_start_bytes, diff -r 4f41766176cf -r af2ab04e0038 src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Sep 08 05:16:49 2011 -0400 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Sep 08 16:29:41 2011 +0200 @@ -185,6 +185,7 @@ bool _adaptive_young_list_length; size_t _young_list_target_length; size_t _young_list_fixed_length; + size_t _prev_eden_capacity; // used for logging // The max number of regions we can extend the eden by while the GC // locker is active. This should be >= _young_list_target_length; @@ -245,6 +246,10 @@ TruncatedSeq* _max_conc_overhead_seq; + bool _using_new_ratio_calculations; + size_t _min_desired_young_length; // as set on the command line or default calculations + size_t _max_desired_young_length; // as set on the command line or default calculations + size_t _recorded_young_regions; size_t _recorded_non_young_regions; size_t _recorded_region_num; @@ -826,9 +831,8 @@ return _all_pause_times_ms->num() + 1; } - // Recalculate the reserve region number. This should be called - // after the heap is resized. - void calculate_reserve(size_t all_regions); + // This should be called after the heap is resized. + void record_new_heap_size(size_t new_number_of_regions); protected: @@ -841,6 +845,8 @@ size_t max_live_bytes); void record_concurrent_mark_cleanup_end_work2(); + void update_young_list_size_using_newratio(size_t number_of_heap_regions); + public: virtual void init();