Print this page
JDK-8236073 G1: Use SoftMaxHeapSize to guide GC heuristics

*** 30,39 **** --- 30,40 ---- #include "gc/g1/g1CollectionSetCandidates.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1CollectionSetChooser.hpp" + #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeterogeneousHeapPolicy.hpp" #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1IHOPControl.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1Policy.hpp"
*** 74,83 **** --- 75,85 ---- _pending_cards_at_prev_gc_end(0), _total_mutator_refined_cards(0), _total_concurrent_refined_cards(0), _total_concurrent_refinement_time(), _bytes_allocated_in_old_since_last_gc(0), + _minimum_desired_bytes_after_last_cm(0), _initial_mark_to_mixed(), _collection_set(NULL), _g1h(NULL), _phase_times(new G1GCPhaseTimes(gc_timer, ParallelGCThreads)), _mark_remark_start_sec(0),
*** 1093,1102 **** --- 1095,1119 ---- log_debug(gc, ergo)("Do not initiate concurrent cycle (concurrent cycle already in progress)"); } } } + void G1Policy::determine_desired_bytes_after_concurrent_mark() { + size_t cur_used_bytes = _g1h->non_young_capacity_bytes(); + + size_t overall_target_capacity = _g1h->heap_sizing_policy()->target_heap_capacity(cur_used_bytes, MinHeapFreeRatio); + + size_t desired_bytes_after_concurrent_mark = _g1h->policy()->desired_bytes_after_concurrent_mark(cur_used_bytes); + + _minimum_desired_bytes_after_last_cm = MIN2(desired_bytes_after_concurrent_mark, overall_target_capacity); + + log_debug(gc, ergo, heap)("Expansion amount after remark used: " SIZE_FORMAT " " + "minimum_desired_capacity " SIZE_FORMAT " desired_bytes_after_concurrent_mark: " SIZE_FORMAT " " + "minimum_desired_bytes_after_concurrent_mark " SIZE_FORMAT, + cur_used_bytes, overall_target_capacity, desired_bytes_after_concurrent_mark, _minimum_desired_bytes_after_last_cm); + } + void G1Policy::record_concurrent_mark_cleanup_end() { G1CollectionSetCandidates* candidates = G1CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions()); _collection_set->set_candidates(candidates); bool mixed_gc_pending = next_gc_should_be_mixed("request mixed gcs", "request young-only gcs");
*** 1105,1114 **** --- 1122,1133 ---- abort_time_to_mixed_tracking(); } collector_state()->set_in_young_gc_before_mixed(mixed_gc_pending); collector_state()->set_mark_or_rebuild_in_progress(false); + determine_desired_bytes_after_concurrent_mark(); + double end_sec = os::elapsedTime(); double elapsed_time_ms = (end_sec - _mark_cleanup_start_sec) * 1000.0; _analytics->report_concurrent_mark_cleanup_times_ms(elapsed_time_ms); _analytics->append_prev_collection_pause_end_ms(elapsed_time_ms);
*** 1197,1222 **** bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) const { G1CollectionSetCandidates* candidates = _collection_set->candidates(); ! if (candidates->is_empty()) { log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); return false; } // Is the amount of uncollected reclaimable space above G1HeapWastePercent? size_t reclaimable_bytes = candidates->remaining_reclaimable_bytes(); double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; if (reclaimable_percent <= threshold) { log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); return false; } log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); return true; } uint G1Policy::calc_min_old_cset_length() const { // The min old CSet region bound is based on the maximum desired --- 1216,1247 ---- bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) const { G1CollectionSetCandidates* candidates = _collection_set->candidates(); ! if (candidates == NULL || candidates->is_empty()) { ! if (false_action_str != NULL) { log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); + } return false; } // Is the amount of uncollected reclaimable space above G1HeapWastePercent? size_t reclaimable_bytes = candidates->remaining_reclaimable_bytes(); double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; if (reclaimable_percent <= threshold) { + if (false_action_str != NULL) { log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + } return false; } + if (true_action_str != NULL) { log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + } return true; } uint G1Policy::calc_min_old_cset_length() const { // The min old CSet region bound is based on the maximum desired
*** 1409,1413 **** --- 1434,1447 ---- // Don't clear the survivor list handles until the start of // the next evacuation pause - we need it in order to re-tag // the survivor regions from this evacuation pause as 'young' // at the start of the next. } + + size_t G1Policy::desired_bytes_after_concurrent_mark(size_t used_bytes) { + size_t minimum_desired_buffer_size = _ihop_control->predict_unrestrained_buffer_size(); + if (minimum_desired_buffer_size != 0) { + return minimum_desired_buffer_size; + } else { + return _young_list_max_length * HeapRegion::GrainBytes + _reserve_regions * HeapRegion::GrainBytes + used_bytes; + } + }