Mercurial > hg > truffle
diff src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 1973:631f79e71e90
6974966: G1: unnecessary direct-to-old allocations
Summary: This change revamps the slow allocation path of G1. Improvements include the following: a) Allocations directly to old regions are now totally banned. G1 now only allows allocations out of young regions (with the only exception being humongous regions). b) The thread that allocates a new region (which is now guaranteed to be young) does not dirty all its cards. Each thread that successfully allocates out of a young region is now responsible for dirtying the cards that corresponding to the "block" that just got allocated. c) allocate_new_tlab() and mem_allocate() are now implemented differently and TLAB allocations are only done by allocate_new_tlab(). d) If a thread schedules an evacuation pause in order to satisfy an allocation request, it will perform the allocation at the end of the safepoint so that the thread that initiated the GC also gets "first pick" of any space made available by the GC. e) If a thread is unable to allocate a humongous object it will schedule an evacuation pause in case it reclaims enough regions so that the humongous allocation can be satisfied aftewards. f) The G1 policy is more careful to set the young list target length to be the survivor number +1. g) Lots of code tidy up, removal, refactoring to make future changes easier.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Tue, 24 Aug 2010 17:24:33 -0400 |
parents | f95d63e2154a |
children | 016a3628c885 |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Nov 23 13:22:55 2010 -0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Aug 24 17:24:33 2010 -0400 @@ -458,8 +458,8 @@ double now_sec = os::elapsedTime(); double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; double alloc_rate_ms = predict_alloc_rate_ms(); - int min_regions = (int) ceil(alloc_rate_ms * when_ms); - int current_region_num = (int) _g1->young_list()->length(); + size_t min_regions = (size_t) ceil(alloc_rate_ms * when_ms); + size_t current_region_num = _g1->young_list()->length(); _young_list_min_length = min_regions + current_region_num; } } @@ -473,9 +473,12 @@ _young_list_target_length = _young_list_fixed_length; else _young_list_target_length = _young_list_fixed_length / 2; - - _young_list_target_length = MAX2(_young_list_target_length, (size_t)1); } + + // Make sure we allow the application to allocate at least one + // region before we need to do a collection again. + size_t min_length = _g1->young_list()->length() + 1; + _young_list_target_length = MAX2(_young_list_target_length, min_length); calculate_survivors_policy(); } @@ -568,7 +571,7 @@ // we should have at least one region in the target young length _young_list_target_length = - MAX2((size_t) 1, final_young_length + _recorded_survivor_regions); + final_young_length + _recorded_survivor_regions; // let's keep an eye of how long we spend on this calculation // right now, I assume that we'll print it when we need it; we @@ -617,8 +620,7 @@ _young_list_min_length); #endif // TRACE_CALC_YOUNG_LENGTH // we'll do the pause as soon as possible by choosing the minimum - _young_list_target_length = - MAX2(_young_list_min_length, (size_t) 1); + _young_list_target_length = _young_list_min_length; } _rs_lengths_prediction = rs_lengths; @@ -801,7 +803,7 @@ _survivor_surv_rate_group->reset(); calculate_young_list_min_length(); calculate_young_list_target_length(); - } +} void G1CollectorPolicy::record_before_bytes(size_t bytes) { _bytes_in_to_space_before_gc += bytes; @@ -824,9 +826,9 @@ gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial"); } - assert(_g1->used_regions() == _g1->recalculate_used_regions(), - "sanity"); - assert(_g1->used() == _g1->recalculate_used(), "sanity"); + assert(_g1->used() == _g1->recalculate_used(), + err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT, + _g1->used(), _g1->recalculate_used())); double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; _all_stop_world_times_ms->add(s_w_t_ms); @@ -2266,24 +2268,13 @@ #endif // PRODUCT } -bool -G1CollectorPolicy::should_add_next_region_to_young_list() { - assert(in_young_gc_mode(), "should be in young GC mode"); - bool ret; - size_t young_list_length = _g1->young_list()->length(); - size_t young_list_max_length = _young_list_target_length; - if (G1FixedEdenSize) { - young_list_max_length -= _max_survivor_regions; - } - if (young_list_length < young_list_max_length) { - ret = true; +void +G1CollectorPolicy::update_region_num(bool young) { + if (young) { ++_region_num_young; } else { - ret = false; ++_region_num_tenured; } - - return ret; } #ifndef PRODUCT @@ -2327,32 +2318,6 @@ } } -bool -G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t - word_size) { - assert(_g1->regions_accounted_for(), "Region leakage!"); - double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; - - size_t young_list_length = _g1->young_list()->length(); - size_t young_list_max_length = _young_list_target_length; - if (G1FixedEdenSize) { - young_list_max_length -= _max_survivor_regions; - } - bool reached_target_length = young_list_length >= young_list_max_length; - - if (in_young_gc_mode()) { - if (reached_target_length) { - assert( young_list_length > 0 && _g1->young_list()->length() > 0, - "invariant" ); - return true; - } - } else { - guarantee( false, "should not reach here" ); - } - - return false; -} - #ifndef PRODUCT class HRSortIndexIsOKClosure: public HeapRegionClosure { CollectionSetChooser* _chooser;