Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8294850: Make rs length/pending card predictors dependent on gc phase #10650

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 37 additions & 14 deletions src/hotspot/share/gc/g1/g1Analytics.cpp
Original file line number Diff line number Diff line change
@@ -78,7 +78,8 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :
_concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_prev_collection_pause_end_ms(0.0),
_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_concurrent_refine_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_dirtied_cards_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_card_merge_to_scan_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
@@ -91,8 +92,10 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :
_constant_other_time_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_non_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_rs_length_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_rs_length_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_rs_length_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_byte_ms_during_cm_seq(new TruncatedSeq(TruncatedSeqLength)),
_recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
_long_term_pause_time_ratio(0.0),
@@ -104,7 +107,7 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :

int index = MIN2(ParallelGCThreads - 1, 7u);

_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
_young_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
// Start with inverse of maximum STW cost.
_concurrent_refine_rate_ms_seq->add(1/cost_per_logged_card_ms_defaults[0]);
// Some applications have very low rates for logging cards.
@@ -193,8 +196,12 @@ void G1Analytics::report_card_merge_to_scan_ratio(double merge_to_scan_ratio, bo
}
}

void G1Analytics::report_rs_length_diff(double rs_length_diff) {
_rs_length_diff_seq->add(rs_length_diff);
void G1Analytics::report_rs_length_diff(double rs_length_diff, bool for_young_gc) {
if (for_young_gc) {
_young_rs_length_diff_seq->add(rs_length_diff);
} else {
_mixed_rs_length_diff_seq->add(rs_length_diff);
}
}

void G1Analytics::report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress) {
@@ -217,12 +224,20 @@ void G1Analytics::report_constant_other_time_ms(double constant_other_time_ms) {
_constant_other_time_ms_seq->add(constant_other_time_ms);
}

void G1Analytics::report_pending_cards(double pending_cards) {
_pending_cards_seq->add(pending_cards);
void G1Analytics::report_pending_cards(double pending_cards, bool for_young_gc) {
if (for_young_gc) {
_young_pending_cards_seq->add(pending_cards);
} else {
_mixed_pending_cards_seq->add(pending_cards);
}
}

void G1Analytics::report_rs_length(double rs_length) {
_rs_length_seq->add(rs_length);
void G1Analytics::report_rs_length(double rs_length, bool for_young_gc) {
if (for_young_gc) {
_young_rs_length_seq->add(rs_length);
} else {
_mixed_rs_length_seq->add(rs_length);
}
}

double G1Analytics::predict_alloc_rate_ms() const {
@@ -301,12 +316,20 @@ double G1Analytics::predict_cleanup_time_ms() const {
return predict_zero_bounded(_concurrent_mark_cleanup_times_ms);
}

size_t G1Analytics::predict_rs_length() const {
return predict_size(_rs_length_seq) + predict_size(_rs_length_diff_seq);
size_t G1Analytics::predict_rs_length(bool for_young_gc) const {
if (for_young_gc || !enough_samples_available(_mixed_rs_length_seq)) {
return predict_size(_young_rs_length_seq) + predict_size(_young_rs_length_diff_seq);
} else {
return predict_size(_mixed_rs_length_seq) + predict_size(_mixed_rs_length_diff_seq);
}
}

size_t G1Analytics::predict_pending_cards() const {
return predict_size(_pending_cards_seq);
size_t G1Analytics::predict_pending_cards(bool for_young_gc) const {
if (for_young_gc || !enough_samples_available(_mixed_pending_cards_seq)) {
return predict_size(_young_pending_cards_seq);
} else {
return predict_size(_mixed_pending_cards_seq);
}
}

double G1Analytics::oldest_known_gc_end_time_sec() const {
19 changes: 11 additions & 8 deletions src/hotspot/share/gc/g1/g1Analytics.hpp
Original file line number Diff line number Diff line change
@@ -45,7 +45,8 @@ class G1Analytics: public CHeapObj<mtGC> {
TruncatedSeq* _alloc_rate_ms_seq;
double _prev_collection_pause_end_ms;

TruncatedSeq* _rs_length_diff_seq;
TruncatedSeq* _young_rs_length_diff_seq;
TruncatedSeq* _mixed_rs_length_diff_seq;
TruncatedSeq* _concurrent_refine_rate_ms_seq;
TruncatedSeq* _dirtied_cards_rate_ms_seq;
// The ratio between the number of merged cards and actually scanned cards, for
@@ -67,8 +68,10 @@ class G1Analytics: public CHeapObj<mtGC> {
TruncatedSeq* _young_other_cost_per_region_ms_seq;
TruncatedSeq* _non_young_other_cost_per_region_ms_seq;

TruncatedSeq* _pending_cards_seq;
TruncatedSeq* _rs_length_seq;
TruncatedSeq* _young_pending_cards_seq;
TruncatedSeq* _mixed_pending_cards_seq;
TruncatedSeq* _young_rs_length_seq;
TruncatedSeq* _mixed_rs_length_seq;

TruncatedSeq* _cost_per_byte_ms_during_cm_seq;

@@ -126,13 +129,13 @@ class G1Analytics: public CHeapObj<mtGC> {
void report_cost_per_card_scan_ms(double cost_per_remset_card_ms, bool for_young_gc);
void report_cost_per_card_merge_ms(double cost_per_card_ms, bool for_young_gc);
void report_card_merge_to_scan_ratio(double cards_per_entry_ratio, bool for_young_gc);
void report_rs_length_diff(double rs_length_diff);
void report_rs_length_diff(double rs_length_diff, bool for_young_gc);
void report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress);
void report_young_other_cost_per_region_ms(double other_cost_per_region_ms);
void report_non_young_other_cost_per_region_ms(double other_cost_per_region_ms);
void report_constant_other_time_ms(double constant_other_time_ms);
void report_pending_cards(double pending_cards);
void report_rs_length(double rs_length);
void report_pending_cards(double pending_cards, bool for_young_gc);
void report_rs_length(double rs_length, bool for_young_gc);

double predict_alloc_rate_ms() const;
int num_alloc_rate_ms() const;
@@ -161,8 +164,8 @@ class G1Analytics: public CHeapObj<mtGC> {

double predict_cleanup_time_ms() const;

size_t predict_rs_length() const;
size_t predict_pending_cards() const;
size_t predict_rs_length(bool for_young_gc) const;
size_t predict_pending_cards(bool for_young_gc) const;

// Add a new GC of the given duration and end time to the record.
void update_recent_gc_times(double end_time_sec, double elapsed_ms);
36 changes: 17 additions & 19 deletions src/hotspot/share/gc/g1/g1Policy.cpp
Original file line number Diff line number Diff line change
@@ -194,8 +194,9 @@ uint G1Policy::calculate_desired_eden_length_by_mmu() const {
}

void G1Policy::update_young_length_bounds() {
update_young_length_bounds(_analytics->predict_pending_cards(),
_analytics->predict_rs_length());
bool for_young_gc = collector_state()->in_young_only_phase();
update_young_length_bounds(_analytics->predict_pending_cards(for_young_gc),
_analytics->predict_rs_length(for_young_gc));
}

void G1Policy::update_young_length_bounds(size_t pending_cards, size_t rs_length) {
@@ -525,14 +526,15 @@ void G1Policy::revise_young_list_target_length_if_necessary(size_t rs_length) {
update_rs_length_prediction(rs_length_prediction);

G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
// We have no measure of the number of cards in the thread log buffers, assume
// these are very few compared to the sum of the two other sources.
// We have no measure of the number of cards in the thread buffers, assume
// these are very few compared to the ones in the DCQS.
update_young_length_bounds(dcqs.num_cards(), rs_length_prediction);
}
}

void G1Policy::update_rs_length_prediction() {
update_rs_length_prediction(_analytics->predict_rs_length());
bool for_young_gc = collector_state()->in_young_only_phase();
update_rs_length_prediction(_analytics->predict_rs_length(for_young_gc));
}

void G1Policy::update_rs_length_prediction(size_t prediction) {
@@ -753,6 +755,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
double pause_time_ms = (end_time_sec - start_time_sec) * 1000.0;

G1GCPauseType this_pause = collector_state()->young_gc_pause_type(concurrent_operation_is_full_mark);
bool is_young_only_pause = G1GCPauseTypeHelper::is_young_only_pause(this_pause);

if (G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause)) {
record_concurrent_mark_init_end();
@@ -806,7 +809,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
maybe_start_marking();
}
} else {
assert(G1GCPauseTypeHelper::is_young_only_pause(this_pause), "must be");
assert(is_young_only_pause, "must be");
}

_eden_surv_rate_group->start_adding_regions();
@@ -830,8 +833,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
average_time_ms(G1GCPhaseTimes::MergeHCC) +
average_time_ms(G1GCPhaseTimes::MergeLB) +
average_time_ms(G1GCPhaseTimes::OptMergeRS);
_analytics->report_cost_per_card_merge_ms(avg_time_merge_cards / total_cards_merged,
G1GCPauseTypeHelper::is_young_only_pause(this_pause));
_analytics->report_cost_per_card_merge_ms(avg_time_merge_cards / total_cards_merged, is_young_only_pause);
}

// Update prediction for card scan
@@ -842,8 +844,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
double avg_time_dirty_card_scan = average_time_ms(G1GCPhaseTimes::ScanHR) +
average_time_ms(G1GCPhaseTimes::OptScanHR);

_analytics->report_cost_per_card_scan_ms(avg_time_dirty_card_scan / total_cards_scanned,
G1GCPauseTypeHelper::is_young_only_pause(this_pause));
_analytics->report_cost_per_card_scan_ms(avg_time_dirty_card_scan / total_cards_scanned, is_young_only_pause);
}

// Update prediction for the ratio between cards from the remembered
@@ -857,12 +858,11 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
if (total_cards_scanned > 0) {
merge_to_scan_ratio = (double) from_rs_length_cards / total_cards_scanned;
}
_analytics->report_card_merge_to_scan_ratio(merge_to_scan_ratio,
G1GCPauseTypeHelper::is_young_only_pause(this_pause));
_analytics->report_card_merge_to_scan_ratio(merge_to_scan_ratio, is_young_only_pause);

const size_t recorded_rs_length = _collection_set->recorded_rs_length();
const size_t rs_length_diff = _rs_length > recorded_rs_length ? _rs_length - recorded_rs_length : 0;
_analytics->report_rs_length_diff(rs_length_diff);
_analytics->report_rs_length_diff(rs_length_diff, is_young_only_pause);

// Update prediction for copy cost per byte
size_t copied_bytes = p->sum_thread_work_items(G1GCPhaseTimes::MergePSS, G1GCPhaseTimes::MergePSSCopiedBytes);
@@ -887,11 +887,8 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
// Do not update RS lengths and the number of pending cards with information from mixed gc:
// these are is wildly different to during young only gc and mess up young gen sizing right
// after the mixed gc phase.
// During mixed gc we do not use them for young gen sizing.
if (G1GCPauseTypeHelper::is_young_only_pause(this_pause)) {
_analytics->report_pending_cards((double) _pending_cards_at_gc_start);
_analytics->report_rs_length((double) _rs_length);
}
_analytics->report_pending_cards((double) _pending_cards_at_gc_start, is_young_only_pause);
_analytics->report_rs_length((double) _rs_length, is_young_only_pause);
}

assert(!(G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause) && collector_state()->mark_or_rebuild_in_progress()),
@@ -1036,7 +1033,8 @@ double G1Policy::predict_base_time_ms(size_t pending_cards,
}

double G1Policy::predict_base_time_ms(size_t pending_cards) const {
size_t rs_length = _analytics->predict_rs_length();
bool for_young_gc = collector_state()->in_young_only_phase();
size_t rs_length = _analytics->predict_rs_length(for_young_gc);
return predict_base_time_ms(pending_cards, rs_length);
}