提交 e49283a2 编写于 作者: T tonyp

6963209: G1: remove the concept of abandoned pauses

Summary: As part of 6944166 we disabled the concept of abandoned pauses (i.e., if the collection set is empty, we would still try to do a pause even if it is to update the RSets and scan the roots). This changeset removes the code and structures associated with abandoned pauses.
Reviewed-by: iveresov, johnc
上级 e6778b56
......@@ -2843,93 +2843,57 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
#endif // YOUNG_LIST_VERBOSE
// Now choose the CS. We may abandon a pause if we find no
// region that will fit in the MMU pause.
bool abandoned = g1_policy()->choose_collection_set(target_pause_time_ms);
g1_policy()->choose_collection_set(target_pause_time_ms);
// Nothing to do if we were unable to choose a collection set.
if (!abandoned) {
#if G1_REM_SET_LOGGING
gclog_or_tty->print_cr("\nAfter pause, heap:");
print();
gclog_or_tty->print_cr("\nAfter pause, heap:");
print();
#endif
PrepareForRSScanningClosure prepare_for_rs_scan;
collection_set_iterate(&prepare_for_rs_scan);
PrepareForRSScanningClosure prepare_for_rs_scan;
collection_set_iterate(&prepare_for_rs_scan);
setup_surviving_young_words();
setup_surviving_young_words();
// Set up the gc allocation regions.
get_gc_alloc_regions();
// Set up the gc allocation regions.
get_gc_alloc_regions();
// Actually do the work...
evacuate_collection_set();
// Actually do the work...
evacuate_collection_set();
free_collection_set(g1_policy()->collection_set());
g1_policy()->clear_collection_set();
free_collection_set(g1_policy()->collection_set());
g1_policy()->clear_collection_set();
cleanup_surviving_young_words();
cleanup_surviving_young_words();
// Start a new incremental collection set for the next pause.
g1_policy()->start_incremental_cset_building();
// Start a new incremental collection set for the next pause.
g1_policy()->start_incremental_cset_building();
// Clear the _cset_fast_test bitmap in anticipation of adding
// regions to the incremental collection set for the next
// evacuation pause.
clear_cset_fast_test();
// Clear the _cset_fast_test bitmap in anticipation of adding
// regions to the incremental collection set for the next
// evacuation pause.
clear_cset_fast_test();
if (g1_policy()->in_young_gc_mode()) {
_young_list->reset_sampled_info();
if (g1_policy()->in_young_gc_mode()) {
_young_list->reset_sampled_info();
// Don't check the whole heap at this point as the
// GC alloc regions from this pause have been tagged
// as survivors and moved on to the survivor list.
// Survivor regions will fail the !is_young() check.
assert(check_young_list_empty(false /* check_heap */),
"young list should be empty");
// Don't check the whole heap at this point as the
// GC alloc regions from this pause have been tagged
// as survivors and moved on to the survivor list.
// Survivor regions will fail the !is_young() check.
assert(check_young_list_empty(false /* check_heap */),
"young list should be empty");
#if YOUNG_LIST_VERBOSE
gclog_or_tty->print_cr("Before recording survivors.\nYoung List:");
_young_list->print();
gclog_or_tty->print_cr("Before recording survivors.\nYoung List:");
_young_list->print();
#endif // YOUNG_LIST_VERBOSE
g1_policy()->record_survivor_regions(_young_list->survivor_length(),
g1_policy()->record_survivor_regions(_young_list->survivor_length(),
_young_list->first_survivor_region(),
_young_list->last_survivor_region());
_young_list->reset_auxilary_lists();
}
} else {
// We have abandoned the current collection. This can only happen
// if we're not doing young or partially young collections, and
// we didn't find an old region that we're able to collect within
// the allowed time.
assert(g1_policy()->collection_set() == NULL, "should be");
assert(_young_list->length() == 0, "because it should be");
// This should be a no-op.
abandon_collection_set(g1_policy()->inc_cset_head());
g1_policy()->clear_incremental_cset();
g1_policy()->stop_incremental_cset_building();
// Start a new incremental collection set for the next pause.
g1_policy()->start_incremental_cset_building();
// Clear the _cset_fast_test bitmap in anticipation of adding
// regions to the incremental collection set for the next
// evacuation pause.
clear_cset_fast_test();
// This looks confusing, because the DPT should really be empty
// at this point -- since we have not done any collection work,
// there should not be any derived pointers in the table to update;
// however, there is some additional state in the DPT which is
// reset at the end of the (null) "gc" here via the following call.
// A better approach might be to split off that state resetting work
// into a separate method that asserts that the DPT is empty and call
// that here. That is deferred for now.
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
_young_list->reset_auxilary_lists();
}
if (evacuation_failed()) {
......@@ -2963,7 +2927,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
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);
g1_policy()->record_collection_pause_end(abandoned);
g1_policy()->record_collection_pause_end();
assert(regions_accounted_for(), "Region leakage.");
......
......@@ -88,7 +88,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
_all_mod_union_times_ms(new NumberSeq()),
_summary(new Summary()),
_abandoned_summary(new AbandonedSummary()),
#ifndef PRODUCT
_cur_clear_ct_time_ms(0.0),
......@@ -1124,7 +1123,7 @@ double G1CollectorPolicy::max_sum (double* data1,
// Anything below that is considered to be zero
#define MIN_TIMER_GRANULARITY 0.0000001
void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
void G1CollectorPolicy::record_collection_pause_end() {
double end_time_sec = os::elapsedTime();
double elapsed_ms = _last_pause_time_ms;
bool parallel = ParallelGCThreads > 0;
......@@ -1134,7 +1133,7 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
size_t cur_used_bytes = _g1->used();
assert(cur_used_bytes == _g1->recalculate_used(), "It should!");
bool last_pause_included_initial_mark = false;
bool update_stats = !abandoned && !_g1->evacuation_failed();
bool update_stats = !_g1->evacuation_failed();
#ifndef PRODUCT
if (G1YoungSurvRateVerbose) {
......@@ -1273,12 +1272,7 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
gclog_or_tty->print_cr(" Recording collection pause(%d)", _n_pauses);
}
PauseSummary* summary;
if (abandoned) {
summary = _abandoned_summary;
} else {
summary = _summary;
}
PauseSummary* summary = _summary;
double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms);
......@@ -1346,61 +1340,58 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
double other_time_ms = elapsed_ms;
if (!abandoned) {
if (_satb_drain_time_set)
other_time_ms -= _cur_satb_drain_time_ms;
if (_satb_drain_time_set) {
other_time_ms -= _cur_satb_drain_time_ms;
}
if (parallel)
other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms;
else
other_time_ms -=
update_rs_time +
ext_root_scan_time + mark_stack_scan_time +
scan_rs_time + obj_copy_time;
if (parallel) {
other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms;
} else {
other_time_ms -=
update_rs_time +
ext_root_scan_time + mark_stack_scan_time +
scan_rs_time + obj_copy_time;
}
if (PrintGCDetails) {
gclog_or_tty->print_cr("%s%s, %1.8lf secs]",
abandoned ? " (abandoned)" : "",
gclog_or_tty->print_cr("%s, %1.8lf secs]",
(last_pause_included_initial_mark) ? " (initial-mark)" : "",
elapsed_ms / 1000.0);
if (!abandoned) {
if (_satb_drain_time_set) {
print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
}
if (_last_satb_drain_processed_buffers >= 0) {
print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
}
if (parallel) {
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
print_par_stats(2, "GC Worker Start Time",
_par_last_gc_worker_start_times_ms, false);
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
print_par_sizes(3, "Processed Buffers",
_par_last_update_rs_processed_buffers, true);
print_par_stats(2, "Ext Root Scanning",
_par_last_ext_root_scan_times_ms);
print_par_stats(2, "Mark Stack Scanning",
_par_last_mark_stack_scan_times_ms);
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms);
print_par_sizes(3, "Termination Attempts",
_par_last_termination_attempts, true);
print_par_stats(2, "GC Worker End Time",
_par_last_gc_worker_end_times_ms, false);
print_stats(2, "Other", parallel_other_time);
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
} else {
print_stats(1, "Update RS", update_rs_time);
print_stats(2, "Processed Buffers",
(int)update_rs_processed_buffers);
print_stats(1, "Ext Root Scanning", ext_root_scan_time);
print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
print_stats(1, "Scan RS", scan_rs_time);
print_stats(1, "Object Copying", obj_copy_time);
}
if (_satb_drain_time_set) {
print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
}
if (_last_satb_drain_processed_buffers >= 0) {
print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
}
if (parallel) {
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
print_par_stats(2, "GC Worker Start Time",
_par_last_gc_worker_start_times_ms, false);
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
print_par_sizes(3, "Processed Buffers",
_par_last_update_rs_processed_buffers, true);
print_par_stats(2, "Ext Root Scanning",
_par_last_ext_root_scan_times_ms);
print_par_stats(2, "Mark Stack Scanning",
_par_last_mark_stack_scan_times_ms);
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms);
print_par_sizes(3, "Termination Attempts",
_par_last_termination_attempts, true);
print_par_stats(2, "GC Worker End Time",
_par_last_gc_worker_end_times_ms, false);
print_stats(2, "Other", parallel_other_time);
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
} else {
print_stats(1, "Update RS", update_rs_time);
print_stats(2, "Processed Buffers",
(int)update_rs_processed_buffers);
print_stats(1, "Ext Root Scanning", ext_root_scan_time);
print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
print_stats(1, "Scan RS", scan_rs_time);
print_stats(1, "Object Copying", obj_copy_time);
}
#ifndef PRODUCT
print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
......@@ -2176,33 +2167,27 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
print_summary(1, "Other", summary->get_other_seq());
{
NumberSeq calc_other_times_ms;
if (body_summary != NULL) {
// not abandoned
if (parallel) {
// parallel
NumberSeq* other_parts[] = {
body_summary->get_satb_drain_seq(),
body_summary->get_parallel_seq(),
body_summary->get_clear_ct_seq()
};
calc_other_times_ms = NumberSeq(summary->get_total_seq(),
3, other_parts);
} else {
// serial
NumberSeq* other_parts[] = {
body_summary->get_satb_drain_seq(),
body_summary->get_update_rs_seq(),
body_summary->get_ext_root_scan_seq(),
body_summary->get_mark_stack_scan_seq(),
body_summary->get_scan_rs_seq(),
body_summary->get_obj_copy_seq()
};
calc_other_times_ms = NumberSeq(summary->get_total_seq(),
7, other_parts);
}
if (parallel) {
// parallel
NumberSeq* other_parts[] = {
body_summary->get_satb_drain_seq(),
body_summary->get_parallel_seq(),
body_summary->get_clear_ct_seq()
};
calc_other_times_ms = NumberSeq(summary->get_total_seq(),
3, other_parts);
} else {
// abandoned
calc_other_times_ms = NumberSeq();
// serial
NumberSeq* other_parts[] = {
body_summary->get_satb_drain_seq(),
body_summary->get_update_rs_seq(),
body_summary->get_ext_root_scan_seq(),
body_summary->get_mark_stack_scan_seq(),
body_summary->get_scan_rs_seq(),
body_summary->get_obj_copy_seq()
};
calc_other_times_ms = NumberSeq(summary->get_total_seq(),
7, other_parts);
}
check_other_times(1, summary->get_other_seq(), &calc_other_times_ms);
}
......@@ -2213,20 +2198,6 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
gclog_or_tty->print_cr("");
}
void
G1CollectorPolicy::print_abandoned_summary(PauseSummary* summary) const {
bool printed = false;
if (summary->get_total_seq()->num() > 0) {
printed = true;
print_summary(summary);
}
if (!printed) {
print_indent(0);
gclog_or_tty->print_cr("none");
gclog_or_tty->print_cr("");
}
}
void G1CollectorPolicy::print_tracing_info() const {
if (TraceGen0Time) {
gclog_or_tty->print_cr("ALL PAUSES");
......@@ -2240,9 +2211,6 @@ void G1CollectorPolicy::print_tracing_info() const {
gclog_or_tty->print_cr("EVACUATION PAUSES");
print_summary(_summary);
gclog_or_tty->print_cr("ABANDONED PAUSES");
print_abandoned_summary(_abandoned_summary);
gclog_or_tty->print_cr("MISC");
print_summary_sd(0, "Stop World", _all_stop_world_times_ms);
print_summary_sd(0, "Yields", _all_yield_times_ms);
......@@ -2868,19 +2836,12 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream
}
#endif // !PRODUCT
bool
void
G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
double target_pause_time_ms) {
// Set this here - in case we're not doing young collections.
double non_young_start_time_sec = os::elapsedTime();
// The result that this routine will return. This will be set to
// false if:
// * we're doing a young or partially young collection and we
// have added the youg regions to collection set, or
// * we add old regions to the collection set.
bool abandon_collection = true;
start_recording_regions();
guarantee(target_pause_time_ms > 0.0,
......@@ -2984,10 +2945,6 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
}
assert(_inc_cset_size == _g1->young_list()->length(), "Invariant");
if (_inc_cset_size > 0) {
assert(_collection_set != NULL, "Invariant");
abandon_collection = false;
}
double young_end_time_sec = os::elapsedTime();
_recorded_young_cset_choice_time_ms =
......@@ -3009,10 +2966,6 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
NumberSeq seq;
double avg_prediction = 100000000000000000.0; // something very large
// Save the current size of the collection set to detect
// if we actually added any old regions.
size_t n_young_regions = _collection_set_size;
do {
hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms,
avg_prediction);
......@@ -3039,12 +2992,6 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
if (!adaptive_young_list_length() &&
_collection_set_size < _young_list_fixed_length)
_should_revert_to_full_young_gcs = true;
if (_collection_set_size > n_young_regions) {
// We actually added old regions to the collection set
// so we are not abandoning this collection.
abandon_collection = false;
}
}
choose_collection_set_end:
......@@ -3057,19 +3004,6 @@ choose_collection_set_end:
double non_young_end_time_sec = os::elapsedTime();
_recorded_non_young_cset_choice_time_ms =
(non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
// Here we are supposed to return whether the pause should be
// abandoned or not (i.e., whether the collection set is empty or
// not). However, this introduces a subtle issue when a pause is
// initiated explicitly with System.gc() and
// +ExplicitGCInvokesConcurrent (see Comment #2 in CR 6944166), it's
// supposed to start a marking cycle, and it's abandoned. So, by
// returning false here we are telling the caller never to consider
// a pause to be abandoned. We'll actually remove all the code
// associated with abandoned pauses as part of CR 6963209, but we are
// just disabling them this way for the moment to avoid increasing
// further the amount of changes for CR 6944166.
return false;
}
void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() {
......@@ -3084,7 +3018,7 @@ expand_if_possible(size_t numRegions) {
}
void G1CollectorPolicy_BestRegionsFirst::
record_collection_pause_end(bool abandoned) {
G1CollectorPolicy::record_collection_pause_end(abandoned);
record_collection_pause_end() {
G1CollectorPolicy::record_collection_pause_end();
assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
}
......@@ -76,9 +76,6 @@ public:
virtual MainBodySummary* main_body_summary() { return this; }
};
class AbandonedSummary: public PauseSummary {
};
class G1CollectorPolicy: public CollectorPolicy {
protected:
// The number of pauses during the execution.
......@@ -148,7 +145,6 @@ protected:
TruncatedSeq* _concurrent_mark_cleanup_times_ms;
Summary* _summary;
AbandonedSummary* _abandoned_summary;
NumberSeq* _all_pause_times_ms;
NumberSeq* _all_full_gc_times_ms;
......@@ -573,7 +569,6 @@ protected:
NumberSeq* calc_other_times_ms) const;
void print_summary (PauseSummary* stats) const;
void print_abandoned_summary(PauseSummary* summary) const;
void print_summary (int level, const char* str, NumberSeq* seq) const;
void print_summary_sd (int level, const char* str, NumberSeq* seq) const;
......@@ -886,7 +881,7 @@ public:
virtual void record_collection_pause_end_CH_strong_roots();
virtual void record_collection_pause_end_G1_strong_roots();
virtual void record_collection_pause_end(bool abandoned);
virtual void record_collection_pause_end();
// Record the fact that a full collection occurred.
virtual void record_full_collection_start();
......@@ -999,7 +994,7 @@ public:
// Choose a new collection set. Marks the chosen regions as being
// "in_collection_set", and links them together. The head and number of
// the collection set are available via access methods.
virtual bool choose_collection_set(double target_pause_time_ms) = 0;
virtual void choose_collection_set(double target_pause_time_ms) = 0;
// The head of the list (via "next_in_collection_set()") representing the
// current collection set.
......@@ -1256,7 +1251,7 @@ class G1CollectorPolicy_BestRegionsFirst: public G1CollectorPolicy {
// If the estimated is less then desirable, resize if possible.
void expand_if_possible(size_t numRegions);
virtual bool choose_collection_set(double target_pause_time_ms);
virtual void choose_collection_set(double target_pause_time_ms);
virtual void record_collection_pause_start(double start_time_sec,
size_t start_used);
virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes,
......@@ -1267,7 +1262,7 @@ public:
G1CollectorPolicy_BestRegionsFirst() {
_collectionSetChooser = new CollectionSetChooser();
}
void record_collection_pause_end(bool abandoned);
void record_collection_pause_end();
bool should_do_collection_pause(size_t word_size);
// This is not needed any more, after the CSet choosing code was
// changed to use the pause prediction work. But let's leave the
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册