--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Nov 17 13:14:49 2011 -0500
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Nov 18 12:52:27 2011 -0500
@@ -36,10 +36,6 @@
#include "runtime/mutexLocker.hpp"
#include "utilities/debug.hpp"
-#define PREDICTIONS_VERBOSE 0
-
-// <NEW PREDICTION>
-
// Different defaults for different number of GC threads
// They were chosen by running GCOld and SPECjbb on debris with different
// numbers of GC threads and choosing them based on the results
@@ -80,8 +76,6 @@
1.0, 0.7, 0.7, 0.5, 0.5, 0.42, 0.42, 0.30
};
-// </NEW PREDICTION>
-
// Help class for avoiding interleaved logging
class LineBuffer: public StackObj {
@@ -137,10 +131,6 @@
_parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads()
? ParallelGCThreads : 1),
- _n_pauses(0),
- _recent_rs_scan_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
- _recent_pause_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
- _recent_rs_sizes(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_all_pause_times_ms(new NumberSeq()),
_stop_world_start(0.0),
@@ -148,8 +138,6 @@
_all_yield_times_ms(new NumberSeq()),
_using_new_ratio_calculations(false),
- _all_mod_union_times_ms(new NumberSeq()),
-
_summary(new Summary()),
_cur_clear_ct_time_ms(0.0),
@@ -165,11 +153,6 @@
_num_cc_clears(0L),
#endif
- _region_num_young(0),
- _region_num_tenured(0),
- _prev_region_num_young(0),
- _prev_region_num_tenured(0),
-
_aux_num(10),
_all_aux_times_ms(new NumberSeq[_aux_num]),
_cur_aux_start_times_ms(new double[_aux_num]),
@@ -179,8 +162,6 @@
_concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
- // <NEW PREDICTION>
-
_alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_prev_collection_pause_end_ms(0.0),
_pending_card_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
@@ -199,13 +180,10 @@
new TruncatedSeq(TruncatedSeqLength)),
_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
- _scanned_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_rs_lengths_seq(new TruncatedSeq(TruncatedSeqLength)),
_pause_time_target_ms((double) MaxGCPauseMillis),
- // </NEW PREDICTION>
-
_full_young_gcs(true),
_full_young_pause_num(0),
_partial_young_pause_num(0),
@@ -221,16 +199,10 @@
_recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
- _recent_CS_bytes_used_before(new TruncatedSeq(NumPrevPausesForHeuristics)),
- _recent_CS_bytes_surviving(new TruncatedSeq(NumPrevPausesForHeuristics)),
-
_recent_avg_pause_time_ratio(0.0),
_all_full_gc_times_ms(new NumberSeq()),
- // G1PausesBtwnConcMark defaults to -1
- // so the hack is to do the cast QQQ FIXME
- _pauses_btwn_concurrent_mark((size_t)G1PausesBtwnConcMark),
_initiate_conc_mark_if_possible(false),
_during_initial_mark_pause(false),
_should_revert_to_full_young_gcs(false),
@@ -242,22 +214,21 @@
_prev_collection_pause_used_at_end_bytes(0),
+ _eden_cset_region_length(0),
+ _survivor_cset_region_length(0),
+ _old_cset_region_length(0),
+
_collection_set(NULL),
- _collection_set_size(0),
_collection_set_bytes_used_before(0),
// Incremental CSet attributes
_inc_cset_build_state(Inactive),
_inc_cset_head(NULL),
_inc_cset_tail(NULL),
- _inc_cset_size(0),
- _inc_cset_young_index(0),
_inc_cset_bytes_used_before(0),
_inc_cset_max_finger(NULL),
- _inc_cset_recorded_young_bytes(0),
_inc_cset_recorded_rs_lengths(0),
_inc_cset_predicted_elapsed_time_ms(0.0),
- _inc_cset_predicted_bytes_to_copy(0),
#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
@@ -325,8 +296,6 @@
// start conservatively
_expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
- // <NEW PREDICTION>
-
int index;
if (ParallelGCThreads == 0)
index = 0;
@@ -348,8 +317,6 @@
_non_young_other_cost_per_region_ms_seq->add(
non_young_other_cost_per_region_ms_defaults[index]);
- // </NEW PREDICTION>
-
// Below, we might need to calculate the pause time target based on
// the pause interval. When we do so we are going to give G1 maximum
// flexibility and allow it to do pauses when it needs to. So, we'll
@@ -908,9 +875,6 @@
record_survivor_regions(0, NULL, NULL);
- _prev_region_num_young = _region_num_young;
- _prev_region_num_tenured = _region_num_tenured;
-
_free_regions_at_end_of_collection = _g1->free_regions();
// Reset survivors SurvRateGroup.
_survivor_surv_rate_group->reset();
@@ -1168,8 +1132,10 @@
double end_time_sec = os::elapsedTime();
double elapsed_ms = _last_pause_time_ms;
bool parallel = G1CollectedHeap::use_parallel_gc_threads();
+ assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(),
+ "otherwise, the subtraction below does not make sense");
size_t rs_size =
- _cur_collection_pause_used_regions_at_start - collection_set_size();
+ _cur_collection_pause_used_regions_at_start - cset_region_length();
size_t cur_used_bytes = _g1->used();
assert(cur_used_bytes == _g1->recalculate_used(), "It should!");
bool last_pause_included_initial_mark = false;
@@ -1226,10 +1192,6 @@
_mmu_tracker->add_pause(end_time_sec - elapsed_ms/1000.0,
end_time_sec, false);
- guarantee(_cur_collection_pause_used_regions_at_start >=
- collection_set_size(),
- "Negative RS size?");
-
// This assert is exempted when we're doing parallel collection pauses,
// because the fragmentation caused by the parallel GC allocation buffers
// can lead to more memory being used during collection than was used
@@ -1253,8 +1215,6 @@
(double)surviving_bytes/
(double)_collection_set_bytes_used_before;
- _n_pauses++;
-
// These values are used to update the summary information that is
// displayed when TraceGen0Time is enabled, and are output as part
// of the PrintGCDetails output, in the non-parallel case.
@@ -1295,10 +1255,6 @@
_all_pause_times_ms->add(elapsed_ms);
if (update_stats) {
- _recent_rs_scan_times_ms->add(scan_rs_time);
- _recent_pause_times_ms->add(elapsed_ms);
- _recent_rs_sizes->add(rs_size);
-
_summary->record_total_time_ms(elapsed_ms);
_summary->record_other_time_ms(other_time_ms);
@@ -1342,9 +1298,6 @@
|| surviving_bytes <= _collection_set_bytes_used_before,
"Or else negative collection!");
- _recent_CS_bytes_used_before->add(_collection_set_bytes_used_before);
- _recent_CS_bytes_surviving->add(surviving_bytes);
-
// this is where we update the allocation rate of the application
double app_time_ms =
(_cur_collection_start_sec * 1000.0 - _prev_collection_pause_end_ms);
@@ -1354,13 +1307,17 @@
// We'll just set it to something (arbitrarily) small.
app_time_ms = 1.0;
}
- size_t regions_allocated =
- (_region_num_young - _prev_region_num_young) +
- (_region_num_tenured - _prev_region_num_tenured);
+ // We maintain the invariant that all objects allocated by mutator
+ // threads will be allocated out of eden regions. So, we can use
+ // the eden region number allocated since the previous GC to
+ // calculate the application's allocate rate. The only exception
+ // to that is humongous objects that are allocated separately. But
+ // given that humongous object allocations do not really affect
+ // either the pause's duration nor when the next pause will take
+ // place we can safely ignore them here.
+ size_t regions_allocated = eden_cset_region_length();
double alloc_rate_ms = (double) regions_allocated / app_time_ms;
_alloc_rate_ms_seq->add(alloc_rate_ms);
- _prev_region_num_young = _region_num_young;
- _prev_region_num_tenured = _region_num_tenured;
double interval_ms =
(end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0;
@@ -1398,33 +1355,6 @@
}
}
-
- if (G1PolicyVerbose > 1) {
- gclog_or_tty->print_cr(" Recording collection pause(%d)", _n_pauses);
- }
-
- if (G1PolicyVerbose > 1) {
- gclog_or_tty->print_cr(" ET: %10.6f ms (avg: %10.6f ms)\n"
- " ET-RS: %10.6f ms (avg: %10.6f ms)\n"
- " |RS|: " SIZE_FORMAT,
- elapsed_ms, recent_avg_time_for_pauses_ms(),
- scan_rs_time, recent_avg_time_for_rs_scan_ms(),
- rs_size);
-
- gclog_or_tty->print_cr(" Used at start: " SIZE_FORMAT"K"
- " At end " SIZE_FORMAT "K\n"
- " garbage : " SIZE_FORMAT "K"
- " of " SIZE_FORMAT "K\n"
- " survival : %6.2f%% (%6.2f%% avg)",
- _cur_collection_pause_used_at_start_bytes/K,
- _g1->used()/K, freed_bytes/K,
- _collection_set_bytes_used_before/K,
- survival_fraction*100.0,
- recent_avg_survival_fraction()*100.0);
- gclog_or_tty->print_cr(" Recent %% gc pause time: %6.2f",
- recent_avg_pause_time_ratio() * 100.0);
- }
-
// PrintGCDetails output
if (PrintGCDetails) {
bool print_marking_info =
@@ -1576,8 +1506,6 @@
_short_lived_surv_rate_group->start_adding_regions();
// do that for any other surv rate groupsx
- // <NEW PREDICTION>
-
if (update_stats) {
double pause_time_ms = elapsed_ms;
@@ -1631,21 +1559,21 @@
_mark_closure_time_ms + termination_time);
double young_other_time_ms = 0.0;
- if (_recorded_young_regions > 0) {
+ if (young_cset_region_length() > 0) {
young_other_time_ms =
_recorded_young_cset_choice_time_ms +
_recorded_young_free_cset_time_ms;
_young_other_cost_per_region_ms_seq->add(young_other_time_ms /
- (double) _recorded_young_regions);
+ (double) young_cset_region_length());
}
double non_young_other_time_ms = 0.0;
- if (_recorded_non_young_regions > 0) {
+ if (old_cset_region_length() > 0) {
non_young_other_time_ms =
_recorded_non_young_cset_choice_time_ms +
_recorded_non_young_free_cset_time_ms;
_non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms /
- (double) _recorded_non_young_regions);
+ (double) old_cset_region_length());
}
double constant_other_time_ms = all_other_time_ms -
@@ -1659,7 +1587,6 @@
}
_pending_cards_seq->add((double) _pending_cards);
- _scanned_cards_seq->add((double) cards_scanned);
_rs_lengths_seq->add((double) _max_rs_lengths);
double expensive_region_limit_ms =
@@ -1670,49 +1597,6 @@
expensive_region_limit_ms = (double) MaxGCPauseMillis;
}
_expensive_region_limit_ms = expensive_region_limit_ms;
-
- if (PREDICTIONS_VERBOSE) {
- gclog_or_tty->print_cr("");
- gclog_or_tty->print_cr("PREDICTIONS %1.4lf %d "
- "REGIONS %d %d %d "
- "PENDING_CARDS %d %d "
- "CARDS_SCANNED %d %d "
- "RS_LENGTHS %d %d "
- "RS_UPDATE %1.6lf %1.6lf RS_SCAN %1.6lf %1.6lf "
- "SURVIVAL_RATIO %1.6lf %1.6lf "
- "OBJECT_COPY %1.6lf %1.6lf OTHER_CONSTANT %1.6lf %1.6lf "
- "OTHER_YOUNG %1.6lf %1.6lf "
- "OTHER_NON_YOUNG %1.6lf %1.6lf "
- "VTIME_DIFF %1.6lf TERMINATION %1.6lf "
- "ELAPSED %1.6lf %1.6lf ",
- _cur_collection_start_sec,
- (!_last_young_gc_full) ? 2 :
- (last_pause_included_initial_mark) ? 1 : 0,
- _recorded_region_num,
- _recorded_young_regions,
- _recorded_non_young_regions,
- _predicted_pending_cards, _pending_cards,
- _predicted_cards_scanned, cards_scanned,
- _predicted_rs_lengths, _max_rs_lengths,
- _predicted_rs_update_time_ms, update_rs_time,
- _predicted_rs_scan_time_ms, scan_rs_time,
- _predicted_survival_ratio, survival_ratio,
- _predicted_object_copy_time_ms, obj_copy_time,
- _predicted_constant_other_time_ms, constant_other_time_ms,
- _predicted_young_other_time_ms, young_other_time_ms,
- _predicted_non_young_other_time_ms,
- non_young_other_time_ms,
- _vtime_diff_ms, termination_time,
- _predicted_pause_time_ms, elapsed_ms);
- }
-
- if (G1PolicyVerbose > 0) {
- gclog_or_tty->print_cr("Pause Time, predicted: %1.4lfms (predicted %s), actual: %1.4lfms",
- _predicted_pause_time_ms,
- (_within_target) ? "within" : "outside",
- elapsed_ms);
- }
-
}
_in_marking_window = new_in_marking_window;
@@ -1723,7 +1607,6 @@
// Note that _mmu_tracker->max_gc_time() returns the time in seconds.
double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
- // </NEW PREDICTION>
assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
}
@@ -1768,8 +1651,6 @@
}
}
-// <NEW PREDICTION>
-
void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
double update_rs_processed_buffers,
double goal_ms) {
@@ -1905,98 +1786,17 @@
}
void
-G1CollectorPolicy::start_recording_regions() {
- _recorded_rs_lengths = 0;
- _recorded_young_regions = 0;
- _recorded_non_young_regions = 0;
-
-#if PREDICTIONS_VERBOSE
- _recorded_marked_bytes = 0;
- _recorded_young_bytes = 0;
- _predicted_bytes_to_copy = 0;
- _predicted_rs_lengths = 0;
- _predicted_cards_scanned = 0;
-#endif // PREDICTIONS_VERBOSE
-}
-
-void
-G1CollectorPolicy::record_cset_region_info(HeapRegion* hr, bool young) {
-#if PREDICTIONS_VERBOSE
- if (!young) {
- _recorded_marked_bytes += hr->max_live_bytes();
- }
- _predicted_bytes_to_copy += predict_bytes_to_copy(hr);
-#endif // PREDICTIONS_VERBOSE
-
- size_t rs_length = hr->rem_set()->occupied();
- _recorded_rs_lengths += rs_length;
-}
-
-void
-G1CollectorPolicy::record_non_young_cset_region(HeapRegion* hr) {
- assert(!hr->is_young(), "should not call this");
- ++_recorded_non_young_regions;
- record_cset_region_info(hr, false);
-}
-
-void
-G1CollectorPolicy::set_recorded_young_regions(size_t n_regions) {
- _recorded_young_regions = n_regions;
-}
-
-void G1CollectorPolicy::set_recorded_young_bytes(size_t bytes) {
-#if PREDICTIONS_VERBOSE
- _recorded_young_bytes = bytes;
-#endif // PREDICTIONS_VERBOSE
+G1CollectorPolicy::init_cset_region_lengths(size_t eden_cset_region_length,
+ size_t survivor_cset_region_length) {
+ _eden_cset_region_length = eden_cset_region_length;
+ _survivor_cset_region_length = survivor_cset_region_length;
+ _old_cset_region_length = 0;
}
void G1CollectorPolicy::set_recorded_rs_lengths(size_t rs_lengths) {
_recorded_rs_lengths = rs_lengths;
}
-void G1CollectorPolicy::set_predicted_bytes_to_copy(size_t bytes) {
- _predicted_bytes_to_copy = bytes;
-}
-
-void
-G1CollectorPolicy::end_recording_regions() {
- // The _predicted_pause_time_ms field is referenced in code
- // not under PREDICTIONS_VERBOSE. Let's initialize it.
- _predicted_pause_time_ms = -1.0;
-
-#if PREDICTIONS_VERBOSE
- _predicted_pending_cards = predict_pending_cards();
- _predicted_rs_lengths = _recorded_rs_lengths + predict_rs_length_diff();
- if (full_young_gcs())
- _predicted_cards_scanned += predict_young_card_num(_predicted_rs_lengths);
- else
- _predicted_cards_scanned +=
- predict_non_young_card_num(_predicted_rs_lengths);
- _recorded_region_num = _recorded_young_regions + _recorded_non_young_regions;
-
- _predicted_rs_update_time_ms =
- predict_rs_update_time_ms(_g1->pending_card_num());
- _predicted_rs_scan_time_ms =
- predict_rs_scan_time_ms(_predicted_cards_scanned);
- _predicted_object_copy_time_ms =
- predict_object_copy_time_ms(_predicted_bytes_to_copy);
- _predicted_constant_other_time_ms =
- predict_constant_other_time_ms();
- _predicted_young_other_time_ms =
- predict_young_other_time_ms(_recorded_young_regions);
- _predicted_non_young_other_time_ms =
- predict_non_young_other_time_ms(_recorded_non_young_regions);
-
- _predicted_pause_time_ms =
- _predicted_rs_update_time_ms +
- _predicted_rs_scan_time_ms +
- _predicted_object_copy_time_ms +
- _predicted_constant_other_time_ms +
- _predicted_young_other_time_ms +
- _predicted_non_young_other_time_ms;
-#endif // PREDICTIONS_VERBOSE
-}
-
void G1CollectorPolicy::check_if_region_is_too_expensive(double
predicted_time_ms) {
// I don't think we need to do this when in young GC mode since
@@ -2013,9 +1813,6 @@
}
}
-// </NEW PREDICTION>
-
-
void G1CollectorPolicy::update_recent_gc_times(double end_time_sec,
double elapsed_ms) {
_recent_gc_times_ms->add(elapsed_ms);
@@ -2023,99 +1820,6 @@
_prev_collection_pause_end_ms = end_time_sec * 1000.0;
}
-double G1CollectorPolicy::recent_avg_time_for_pauses_ms() {
- if (_recent_pause_times_ms->num() == 0) {
- return (double) MaxGCPauseMillis;
- }
- return _recent_pause_times_ms->avg();
-}
-
-double G1CollectorPolicy::recent_avg_time_for_rs_scan_ms() {
- if (_recent_rs_scan_times_ms->num() == 0) {
- return (double)MaxGCPauseMillis/3.0;
- }
- return _recent_rs_scan_times_ms->avg();
-}
-
-int G1CollectorPolicy::number_of_recent_gcs() {
- assert(_recent_rs_scan_times_ms->num() ==
- _recent_pause_times_ms->num(), "Sequence out of sync");
- assert(_recent_pause_times_ms->num() ==
- _recent_CS_bytes_used_before->num(), "Sequence out of sync");
- assert(_recent_CS_bytes_used_before->num() ==
- _recent_CS_bytes_surviving->num(), "Sequence out of sync");
-
- return _recent_pause_times_ms->num();
-}
-
-double G1CollectorPolicy::recent_avg_survival_fraction() {
- return recent_avg_survival_fraction_work(_recent_CS_bytes_surviving,
- _recent_CS_bytes_used_before);
-}
-
-double G1CollectorPolicy::last_survival_fraction() {
- return last_survival_fraction_work(_recent_CS_bytes_surviving,
- _recent_CS_bytes_used_before);
-}
-
-double
-G1CollectorPolicy::recent_avg_survival_fraction_work(TruncatedSeq* surviving,
- TruncatedSeq* before) {
- assert(surviving->num() == before->num(), "Sequence out of sync");
- if (before->sum() > 0.0) {
- double recent_survival_rate = surviving->sum() / before->sum();
- // We exempt parallel collection from this check because Alloc Buffer
- // fragmentation can produce negative collections.
- // Further, we're now always doing parallel collection. But I'm still
- // leaving this here as a placeholder for a more precise assertion later.
- // (DLD, 10/05.)
- assert((true || G1CollectedHeap::use_parallel_gc_threads()) ||
- _g1->evacuation_failed() ||
- recent_survival_rate <= 1.0, "Or bad frac");
- return recent_survival_rate;
- } else {
- return 1.0; // Be conservative.
- }
-}
-
-double
-G1CollectorPolicy::last_survival_fraction_work(TruncatedSeq* surviving,
- TruncatedSeq* before) {
- assert(surviving->num() == before->num(), "Sequence out of sync");
- if (surviving->num() > 0 && before->last() > 0.0) {
- double last_survival_rate = surviving->last() / before->last();
- // We exempt parallel collection from this check because Alloc Buffer
- // fragmentation can produce negative collections.
- // Further, we're now always doing parallel collection. But I'm still
- // leaving this here as a placeholder for a more precise assertion later.
- // (DLD, 10/05.)
- assert((true || G1CollectedHeap::use_parallel_gc_threads()) ||
- last_survival_rate <= 1.0, "Or bad frac");
- return last_survival_rate;
- } else {
- return 1.0;
- }
-}
-
-static const int survival_min_obs = 5;
-static double survival_min_obs_limits[] = { 0.9, 0.7, 0.5, 0.3, 0.1 };
-static const double min_survival_rate = 0.1;
-
-double
-G1CollectorPolicy::conservative_avg_survival_fraction_work(double avg,
- double latest) {
- double res = avg;
- if (number_of_recent_gcs() < survival_min_obs) {
- res = MAX2(res, survival_min_obs_limits[number_of_recent_gcs()]);
- }
- res = MAX2(res, latest);
- res = MAX2(res, min_survival_rate);
- // In the parallel case, LAB fragmentation can produce "negative
- // collections"; so can evac failure. Cap at 1.0
- res = MIN2(res, 1.0);
- return res;
-}
-
size_t G1CollectorPolicy::expansion_amount() {
double recent_gc_overhead = recent_avg_pause_time_ratio() * 100.0;
double threshold = _gc_overhead_perc;
@@ -2331,15 +2035,6 @@
print_summary_sd(0, buffer, &_all_aux_times_ms[i]);
}
}
-
- size_t all_region_num = _region_num_young + _region_num_tenured;
- gclog_or_tty->print_cr(" New Regions %8d, Young %8d (%6.2lf%%), "
- "Tenured %8d (%6.2lf%%)",
- all_region_num,
- _region_num_young,
- (double) _region_num_young / (double) all_region_num * 100.0,
- _region_num_tenured,
- (double) _region_num_tenured / (double) all_region_num * 100.0);
}
if (TraceGen1Time) {
if (_all_full_gc_times_ms->num() > 0) {
@@ -2361,14 +2056,6 @@
#endif // PRODUCT
}
-void G1CollectorPolicy::update_region_num(bool young) {
- if (young) {
- ++_region_num_young;
- } else {
- ++_region_num_tenured;
- }
-}
-
#ifndef PRODUCT
// for debugging, bit of a hack...
static char*
@@ -2682,8 +2369,7 @@
}
// Add the heap region at the head of the non-incremental collection set
-void G1CollectorPolicy::
-add_to_collection_set(HeapRegion* hr) {
+void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) {
assert(_inc_cset_build_state == Active, "Precondition");
assert(!hr->is_young(), "non-incremental add of young region");
@@ -2694,9 +2380,11 @@
hr->set_in_collection_set(true);
hr->set_next_in_collection_set(_collection_set);
_collection_set = hr;
- _collection_set_size++;
_collection_set_bytes_used_before += hr->used();
_g1->register_region_with_in_cset_fast_test(hr);
+ size_t rs_length = hr->rem_set()->occupied();
+ _recorded_rs_lengths += rs_length;
+ _old_cset_region_length += 1;
}
// Initialize the per-collection-set information
@@ -2705,16 +2393,11 @@
_inc_cset_head = NULL;
_inc_cset_tail = NULL;
- _inc_cset_size = 0;
_inc_cset_bytes_used_before = 0;
- _inc_cset_young_index = 0;
-
_inc_cset_max_finger = 0;
- _inc_cset_recorded_young_bytes = 0;
_inc_cset_recorded_rs_lengths = 0;
_inc_cset_predicted_elapsed_time_ms = 0;
- _inc_cset_predicted_bytes_to_copy = 0;
_inc_cset_build_state = Active;
}
@@ -2745,20 +2428,6 @@
// rset sampling code
hr->set_recorded_rs_length(rs_length);
hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
-
-#if PREDICTIONS_VERBOSE
- size_t bytes_to_copy = predict_bytes_to_copy(hr);
- _inc_cset_predicted_bytes_to_copy += bytes_to_copy;
-
- // Record the number of bytes used in this region
- _inc_cset_recorded_young_bytes += used_bytes;
-
- // Cache the values we have added to the aggregated informtion
- // in the heap region in case we have to remove this region from
- // the incremental collection set, or it is updated by the
- // rset sampling code
- hr->set_predicted_bytes_to_copy(bytes_to_copy);
-#endif // PREDICTIONS_VERBOSE
}
void G1CollectorPolicy::remove_from_incremental_cset_info(HeapRegion* hr) {
@@ -2784,17 +2453,6 @@
// Clear the values cached in the heap region
hr->set_recorded_rs_length(0);
hr->set_predicted_elapsed_time_ms(0);
-
-#if PREDICTIONS_VERBOSE
- size_t old_predicted_bytes_to_copy = hr->predicted_bytes_to_copy();
- _inc_cset_predicted_bytes_to_copy -= old_predicted_bytes_to_copy;
-
- // Subtract the number of bytes used in this region
- _inc_cset_recorded_young_bytes -= used_bytes;
-
- // Clear the values cached in the heap region
- hr->set_predicted_bytes_to_copy(0);
-#endif // PREDICTIONS_VERBOSE
}
void G1CollectorPolicy::update_incremental_cset_info(HeapRegion* hr, size_t new_rs_length) {
@@ -2806,8 +2464,8 @@
}
void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) {
- assert( hr->is_young(), "invariant");
- assert( hr->young_index_in_cset() == -1, "invariant" );
+ assert(hr->is_young(), "invariant");
+ assert(hr->young_index_in_cset() > -1, "should have already been set");
assert(_inc_cset_build_state == Active, "Precondition");
// We need to clear and set the cached recorded/cached collection set
@@ -2827,11 +2485,7 @@
hr->set_in_collection_set(true);
assert( hr->next_in_collection_set() == NULL, "invariant");
- _inc_cset_size++;
_g1->register_region_with_in_cset_fast_test(hr);
-
- hr->set_young_index_in_cset((int) _inc_cset_young_index);
- ++_inc_cset_young_index;
}
// Add the region at the RHS of the incremental cset
@@ -2899,8 +2553,6 @@
YoungList* young_list = _g1->young_list();
- start_recording_regions();
-
guarantee(target_pause_time_ms > 0.0,
err_msg("target_pause_time_ms = %1.6lf should be positive",
target_pause_time_ms));
@@ -2923,7 +2575,6 @@
if (time_remaining_ms < threshold) {
double prev_time_remaining_ms = time_remaining_ms;
time_remaining_ms = 0.50 * target_pause_time_ms;
- _within_target = false;
ergo_verbose3(ErgoCSetConstruction,
"adjust remaining time",
ergo_format_reason("remaining time lower than threshold")
@@ -2931,8 +2582,6 @@
ergo_format_ms("threshold")
ergo_format_ms("adjusted remaining time"),
prev_time_remaining_ms, threshold, time_remaining_ms);
- } else {
- _within_target = true;
}
size_t expansion_bytes = _g1->expansion_regions() * HeapRegion::GrainBytes;
@@ -2941,8 +2590,6 @@
double young_start_time_sec = os::elapsedTime();
_collection_set_bytes_used_before = 0;
- _collection_set_size = 0;
- _young_cset_length = 0;
_last_young_gc_full = full_young_gcs() ? true : false;
if (_last_young_gc_full) {
@@ -2955,9 +2602,9 @@
// pause are appended to the RHS of the young list, i.e.
// [Newly Young Regions ++ Survivors from last pause].
- size_t survivor_region_num = young_list->survivor_length();
- size_t eden_region_num = young_list->length() - survivor_region_num;
- size_t old_region_num = 0;
+ size_t survivor_region_length = young_list->survivor_length();
+ size_t eden_region_length = young_list->length() - survivor_region_length;
+ init_cset_region_lengths(eden_region_length, survivor_region_length);
hr = young_list->first_survivor_region();
while (hr != NULL) {
assert(hr->is_survivor(), "badly formed young list");
@@ -2971,9 +2618,7 @@
if (_g1->mark_in_progress())
_g1->concurrent_mark()->register_collection_set_finger(_inc_cset_max_finger);
- _young_cset_length = _inc_cset_young_index;
_collection_set = _inc_cset_head;
- _collection_set_size = _inc_cset_size;
_collection_set_bytes_used_before = _inc_cset_bytes_used_before;
time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms;
predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
@@ -2983,19 +2628,12 @@
ergo_format_region("eden")
ergo_format_region("survivors")
ergo_format_ms("predicted young region time"),
- eden_region_num, survivor_region_num,
+ eden_region_length, survivor_region_length,
_inc_cset_predicted_elapsed_time_ms);
// The number of recorded young regions is the incremental
// collection set's current size
- set_recorded_young_regions(_inc_cset_size);
set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths);
- set_recorded_young_bytes(_inc_cset_recorded_young_bytes);
-#if PREDICTIONS_VERBOSE
- set_predicted_bytes_to_copy(_inc_cset_predicted_bytes_to_copy);
-#endif // PREDICTIONS_VERBOSE
-
- assert(_inc_cset_size == young_list->length(), "Invariant");
double young_end_time_sec = os::elapsedTime();
_recorded_young_cset_choice_time_ms =
@@ -3009,9 +2647,16 @@
NumberSeq seq;
double avg_prediction = 100000000000000000.0; // something very large
- size_t prev_collection_set_size = _collection_set_size;
double prev_predicted_pause_time_ms = predicted_pause_time_ms;
do {
+ // Note that add_old_region_to_cset() increments the
+ // _old_cset_region_length field and cset_region_length() returns the
+ // sum of _eden_cset_region_length, _survivor_cset_region_length, and
+ // _old_cset_region_length. So, as old regions are added to the
+ // CSet, _old_cset_region_length will be incremented and
+ // cset_region_length(), which is used below, will always reflect
+ // the the total number of regions added up to this point to the CSet.
+
hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms,
avg_prediction);
if (hr != NULL) {
@@ -3019,8 +2664,7 @@
double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
time_remaining_ms -= predicted_time_ms;
predicted_pause_time_ms += predicted_time_ms;
- add_to_collection_set(hr);
- record_non_young_cset_region(hr);
+ add_old_region_to_cset(hr);
seq.add(predicted_time_ms);
avg_prediction = seq.avg() + seq.sd();
}
@@ -3041,13 +2685,13 @@
should_continue = false;
}
} else {
- if (_collection_set_size >= _young_list_fixed_length) {
+ if (cset_region_length() >= _young_list_fixed_length) {
ergo_verbose2(ErgoCSetConstruction,
"stop adding old regions to CSet",
ergo_format_reason("CSet length reached target")
ergo_format_region("CSet")
ergo_format_region("young target"),
- _collection_set_size, _young_list_fixed_length);
+ cset_region_length(), _young_list_fixed_length);
should_continue = false;
}
}
@@ -3055,23 +2699,21 @@
} while (should_continue);
if (!adaptive_young_list_length() &&
- _collection_set_size < _young_list_fixed_length) {
+ cset_region_length() < _young_list_fixed_length) {
ergo_verbose2(ErgoCSetConstruction,
"request partially-young GCs end",
ergo_format_reason("CSet length lower than target")
ergo_format_region("CSet")
ergo_format_region("young target"),
- _collection_set_size, _young_list_fixed_length);
+ cset_region_length(), _young_list_fixed_length);
_should_revert_to_full_young_gcs = true;
}
- old_region_num = _collection_set_size - prev_collection_set_size;
-
ergo_verbose2(ErgoCSetConstruction | ErgoHigh,
"add old regions to CSet",
ergo_format_region("old")
ergo_format_ms("predicted old region time"),
- old_region_num,
+ old_cset_region_length(),
predicted_pause_time_ms - prev_predicted_pause_time_ms);
}
@@ -3079,8 +2721,6 @@
count_CS_bytes_used();
- end_recording_regions();
-
ergo_verbose5(ErgoCSetConstruction,
"finish choosing CSet",
ergo_format_region("eden")
@@ -3088,7 +2728,8 @@
ergo_format_region("old")
ergo_format_ms("predicted pause time")
ergo_format_ms("target pause time"),
- eden_region_num, survivor_region_num, old_region_num,
+ eden_region_length, survivor_region_length,
+ old_cset_region_length(),
predicted_pause_time_ms, target_pause_time_ms);
double non_young_end_time_sec = os::elapsedTime();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Nov 17 13:14:49 2011 -0500
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Nov 18 12:52:27 2011 -0500
@@ -85,9 +85,6 @@
class G1CollectorPolicy: public CollectorPolicy {
private:
- // The number of pauses during the execution.
- long _n_pauses;
-
// either equal to the number of parallel threads, if ParallelGCThreads
// has been set, or 1 otherwise
int _parallel_gc_threads;
@@ -127,18 +124,9 @@
jlong _num_cc_clears; // number of times the card count cache has been cleared
#endif
- // Statistics for recent GC pauses. See below for how indexed.
- TruncatedSeq* _recent_rs_scan_times_ms;
-
// These exclude marking times.
- TruncatedSeq* _recent_pause_times_ms;
TruncatedSeq* _recent_gc_times_ms;
- TruncatedSeq* _recent_CS_bytes_used_before;
- TruncatedSeq* _recent_CS_bytes_surviving;
-
- TruncatedSeq* _recent_rs_sizes;
-
TruncatedSeq* _concurrent_mark_remark_times_ms;
TruncatedSeq* _concurrent_mark_cleanup_times_ms;
@@ -150,13 +138,6 @@
NumberSeq* _all_stop_world_times_ms;
NumberSeq* _all_yield_times_ms;
- size_t _region_num_young;
- size_t _region_num_tenured;
- size_t _prev_region_num_young;
- size_t _prev_region_num_tenured;
-
- NumberSeq* _all_mod_union_times_ms;
-
int _aux_num;
NumberSeq* _all_aux_times_ms;
double* _cur_aux_start_times_ms;
@@ -194,7 +175,6 @@
// locker is active. This should be >= _young_list_target_length;
size_t _young_list_max_length;
- size_t _young_cset_length;
bool _last_young_gc_full;
unsigned _full_young_pause_num;
@@ -217,8 +197,6 @@
return _during_marking;
}
- // <NEW PREDICTION>
-
private:
enum PredictionConstants {
TruncatedSeqLength = 10
@@ -240,47 +218,32 @@
TruncatedSeq* _non_young_other_cost_per_region_ms_seq;
TruncatedSeq* _pending_cards_seq;
- TruncatedSeq* _scanned_cards_seq;
TruncatedSeq* _rs_lengths_seq;
TruncatedSeq* _cost_per_byte_ms_during_cm_seq;
TruncatedSeq* _young_gc_eff_seq;
- 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;
+ size_t _eden_cset_region_length;
+ size_t _survivor_cset_region_length;
+ size_t _old_cset_region_length;
+
+ void init_cset_region_lengths(size_t eden_cset_region_length,
+ size_t survivor_cset_region_length);
+
+ size_t eden_cset_region_length() { return _eden_cset_region_length; }
+ size_t survivor_cset_region_length() { return _survivor_cset_region_length; }
+ size_t old_cset_region_length() { return _old_cset_region_length; }
size_t _free_regions_at_end_of_collection;
size_t _recorded_rs_lengths;
size_t _max_rs_lengths;
- size_t _recorded_marked_bytes;
- size_t _recorded_young_bytes;
-
- size_t _predicted_pending_cards;
- size_t _predicted_cards_scanned;
- size_t _predicted_rs_lengths;
- size_t _predicted_bytes_to_copy;
-
- double _predicted_survival_ratio;
- double _predicted_rs_update_time_ms;
- double _predicted_rs_scan_time_ms;
- double _predicted_object_copy_time_ms;
- double _predicted_constant_other_time_ms;
- double _predicted_young_other_time_ms;
- double _predicted_non_young_other_time_ms;
- double _predicted_pause_time_ms;
-
- double _vtime_diff_ms;
-
double _recorded_young_free_cset_time_ms;
double _recorded_non_young_free_cset_time_ms;
@@ -320,18 +283,21 @@
double _pause_time_target_ms;
double _recorded_young_cset_choice_time_ms;
double _recorded_non_young_cset_choice_time_ms;
- bool _within_target;
size_t _pending_cards;
size_t _max_pending_cards;
public:
- void set_region_short_lived(HeapRegion* hr) {
+ void set_region_eden(HeapRegion* hr, int young_index_in_cset) {
+ hr->set_young();
hr->install_surv_rate_group(_short_lived_surv_rate_group);
+ hr->set_young_index_in_cset(young_index_in_cset);
}
- void set_region_survivors(HeapRegion* hr) {
+ void set_region_survivor(HeapRegion* hr, int young_index_in_cset) {
+ assert(hr->is_young() && hr->is_survivor(), "pre-condition");
hr->install_surv_rate_group(_survivor_surv_rate_group);
+ hr->set_young_index_in_cset(young_index_in_cset);
}
#ifndef PRODUCT
@@ -343,10 +309,6 @@
seq->davg() * confidence_factor(seq->num()));
}
- size_t young_cset_length() {
- return _young_cset_length;
- }
-
void record_max_rs_lengths(size_t rs_lengths) {
_max_rs_lengths = rs_lengths;
}
@@ -465,20 +427,12 @@
size_t predict_bytes_to_copy(HeapRegion* hr);
double predict_region_elapsed_time_ms(HeapRegion* hr, bool young);
- void start_recording_regions();
- void record_cset_region_info(HeapRegion* hr, bool young);
- void record_non_young_cset_region(HeapRegion* hr);
+ void set_recorded_rs_lengths(size_t rs_lengths);
- void set_recorded_young_regions(size_t n_regions);
- void set_recorded_young_bytes(size_t bytes);
- void set_recorded_rs_lengths(size_t rs_lengths);
- void set_predicted_bytes_to_copy(size_t bytes);
-
- void end_recording_regions();
-
- void record_vtime_diff_ms(double vtime_diff_ms) {
- _vtime_diff_ms = vtime_diff_ms;
- }
+ size_t cset_region_length() { return young_cset_region_length() +
+ old_cset_region_length(); }
+ size_t young_cset_region_length() { return eden_cset_region_length() +
+ survivor_cset_region_length(); }
void record_young_free_cset_time_ms(double time_ms) {
_recorded_young_free_cset_time_ms = time_ms;
@@ -494,8 +448,6 @@
double predict_survivor_regions_evac_time();
- // </NEW PREDICTION>
-
void cset_regions_freed() {
bool propagate = _last_young_gc_full && !_in_marking_window;
_short_lived_surv_rate_group->all_surviving_words_recorded(propagate);
@@ -576,7 +528,6 @@
double max_sum (double* data1, double* data2);
int _last_satb_drain_processed_buffers;
- int _last_update_rs_processed_buffers;
double _last_pause_time_ms;
size_t _bytes_in_collection_set_before_gc;
@@ -596,10 +547,6 @@
// set at the start of the pause.
HeapRegion* _collection_set;
- // The number of regions in the collection set. Set from the incrementally
- // built collection set at the start of an evacuation pause.
- size_t _collection_set_size;
-
// The number of bytes in the collection set before the pause. Set from
// the incrementally built collection set at the start of an evacuation
// pause.
@@ -622,16 +569,6 @@
// The tail of the incrementally built collection set.
HeapRegion* _inc_cset_tail;
- // The number of regions in the incrementally built collection set.
- // Used to set _collection_set_size at the start of an evacuation
- // pause.
- size_t _inc_cset_size;
-
- // Used as the index in the surving young words structure
- // which tracks the amount of space, for each young region,
- // that survives the pause.
- size_t _inc_cset_young_index;
-
// The number of bytes in the incrementally built collection set.
// Used to set _collection_set_bytes_used_before at the start of
// an evacuation pause.
@@ -640,11 +577,6 @@
// Used to record the highest end of heap region in collection set
HeapWord* _inc_cset_max_finger;
- // The number of recorded used bytes in the young regions
- // of the collection set. This is the sum of the used() bytes
- // of retired young regions in the collection set.
- size_t _inc_cset_recorded_young_bytes;
-
// The RSet lengths recorded for regions in the collection set
// (updated by the periodic sampling of the regions in the
// young list/collection set).
@@ -655,68 +587,9 @@
// regions in the young list/collection set).
double _inc_cset_predicted_elapsed_time_ms;
- // The predicted bytes to copy for the regions in the collection
- // set (updated by the periodic sampling of the regions in the
- // young list/collection set).
- size_t _inc_cset_predicted_bytes_to_copy;
-
// Stash a pointer to the g1 heap.
G1CollectedHeap* _g1;
- // The average time in ms per collection pause, averaged over recent pauses.
- double recent_avg_time_for_pauses_ms();
-
- // The average time in ms for RS scanning, per pause, averaged
- // over recent pauses. (Note the RS scanning time for a pause
- // is itself an average of the RS scanning time for each worker
- // thread.)
- double recent_avg_time_for_rs_scan_ms();
-
- // The number of "recent" GCs recorded in the number sequences
- int number_of_recent_gcs();
-
- // The average survival ratio, computed by the total number of bytes
- // suriviving / total number of bytes before collection over the last
- // several recent pauses.
- double recent_avg_survival_fraction();
- // The survival fraction of the most recent pause; if there have been no
- // pauses, returns 1.0.
- double last_survival_fraction();
-
- // Returns a "conservative" estimate of the recent survival rate, i.e.,
- // one that may be higher than "recent_avg_survival_fraction".
- // This is conservative in several ways:
- // If there have been few pauses, it will assume a potential high
- // variance, and err on the side of caution.
- // It puts a lower bound (currently 0.1) on the value it will return.
- // To try to detect phase changes, if the most recent pause ("latest") has a
- // higher-than average ("avg") survival rate, it returns that rate.
- // "work" version is a utility function; young is restricted to young regions.
- double conservative_avg_survival_fraction_work(double avg,
- double latest);
-
- // The arguments are the two sequences that keep track of the number of bytes
- // surviving and the total number of bytes before collection, resp.,
- // over the last evereal recent pauses
- // Returns the survival rate for the category in the most recent pause.
- // If there have been no pauses, returns 1.0.
- double last_survival_fraction_work(TruncatedSeq* surviving,
- TruncatedSeq* before);
-
- // The arguments are the two sequences that keep track of the number of bytes
- // surviving and the total number of bytes before collection, resp.,
- // over the last several recent pauses
- // Returns the average survival ration over the last several recent pauses
- // If there have been no pauses, return 1.0
- double recent_avg_survival_fraction_work(TruncatedSeq* surviving,
- TruncatedSeq* before);
-
- double conservative_avg_survival_fraction() {
- double avg = recent_avg_survival_fraction();
- double latest = last_survival_fraction();
- return conservative_avg_survival_fraction_work(avg, latest);
- }
-
// The ratio of gc time to elapsed time, computed over recent pauses.
double _recent_avg_pause_time_ratio;
@@ -724,9 +597,6 @@
return _recent_avg_pause_time_ratio;
}
- // Number of pauses between concurrent marking.
- size_t _pauses_btwn_concurrent_mark;
-
// At the end of a pause we check the heap occupancy and we decide
// whether we will start a marking cycle during the next pause. If
// we decide that we want to do that, we will set this parameter to
@@ -849,9 +719,6 @@
GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; }
- // The number of collection pauses so far.
- long n_pauses() const { return _n_pauses; }
-
// Update the heuristic info to record a collection pause of the given
// start time, where the given number of bytes were used at the start.
// This may involve changing the desired size of a collection set.
@@ -905,10 +772,6 @@
_last_satb_drain_processed_buffers = processed_buffers;
}
- void record_mod_union_time(double ms) {
- _all_mod_union_times_ms->add(ms);
- }
-
void record_update_rs_time(int thread, double ms) {
_par_last_update_rs_times_ms[thread] = ms;
}
@@ -1009,11 +872,8 @@
void clear_collection_set() { _collection_set = NULL; }
- // The number of elements in the current collection set.
- size_t collection_set_size() { return _collection_set_size; }
-
- // Add "hr" to the CS.
- void add_to_collection_set(HeapRegion* hr);
+ // Add old region "hr" to the CSet.
+ void add_old_region_to_cset(HeapRegion* hr);
// Incremental CSet Support
@@ -1023,9 +883,6 @@
// The tail of the incrementally built collection set.
HeapRegion* inc_set_tail() { return _inc_cset_tail; }
- // The number of elements in the incrementally built collection set.
- size_t inc_cset_size() { return _inc_cset_size; }
-
// Initialize incremental collection set info.
void start_incremental_cset_building();
@@ -1125,8 +982,6 @@
return _young_list_max_length;
}
- void update_region_num(bool young);
-
bool full_young_gcs() {
return _full_young_gcs;
}