Skip to content

Commit 4761479

Browse files
Ivan WalulyaThomas Schatzl
andcommitted
8238687: Investigate memory uncommit during young collections in G1
8247843: Reconsider G1 default GCTimeRatio value 8248324: G1: Remove resizing during Remark Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org> Reviewed-by: kbarrett, tschatzl
1 parent fe26467 commit 4761479

16 files changed

+529
-223
lines changed

src/hotspot/share/gc/g1/g1Analytics.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class G1Analytics: public CHeapObj<mtGC> {
110110
return _short_term_pause_time_ratio;
111111
}
112112

113-
uint number_of_recorded_pause_times() const {
113+
static constexpr uint max_num_of_recorded_pause_times() {
114114
return NumPrevPausesForHeuristics;
115115
}
116116

src/hotspot/share/gc/g1/g1Arguments.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ void G1Arguments::initialize() {
196196
if (FLAG_IS_DEFAULT(GCTimeRatio) || GCTimeRatio == 0) {
197197
// In G1, we want the default GC overhead goal to be higher than
198198
// it is for PS, or the heap might be expanded too aggressively.
199-
// We set it here to ~8%.
200-
FLAG_SET_DEFAULT(GCTimeRatio, 12);
199+
// We set it here to 4%.
200+
FLAG_SET_DEFAULT(GCTimeRatio, 24);
201201
}
202202

203203
// Below, we might need to calculate the pause time interval based on

src/hotspot/share/gc/g1/g1CollectedHeap.cpp

Lines changed: 82 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -795,8 +795,7 @@ void G1CollectedHeap::prepare_for_mutator_after_full_collection(size_t allocatio
795795
assert(num_free_regions() == 0, "we should not have added any free regions");
796796
rebuild_region_sets(false /* free_list_only */);
797797
abort_refinement();
798-
resize_heap_if_necessary(allocation_word_size);
799-
uncommit_regions_if_necessary();
798+
resize_heap_after_full_collection(allocation_word_size);
800799

801800
// Rebuild the code root lists for each region
802801
rebuild_code_roots();
@@ -879,21 +878,41 @@ void G1CollectedHeap::upgrade_to_full_collection() {
879878
size_t(0) /* allocation_word_size */);
880879
}
881880

882-
void G1CollectedHeap::resize_heap_if_necessary(size_t allocation_word_size) {
881+
882+
void G1CollectedHeap::resize_heap(size_t resize_bytes, bool should_expand) {
883+
if (should_expand) {
884+
expand(resize_bytes, _workers);
885+
} else {
886+
shrink(resize_bytes);
887+
uncommit_regions_if_necessary();
888+
}
889+
}
890+
891+
void G1CollectedHeap::resize_heap_after_full_collection(size_t allocation_word_size) {
883892
assert_at_safepoint_on_vm_thread();
884893

885894
bool should_expand;
886-
size_t resize_amount = _heap_sizing_policy->full_collection_resize_amount(should_expand, allocation_word_size);
895+
size_t resize_bytes = _heap_sizing_policy->full_collection_resize_amount(should_expand, allocation_word_size);
887896

888-
if (resize_amount == 0) {
889-
return;
890-
} else if (should_expand) {
891-
expand(resize_amount, _workers);
892-
} else {
893-
shrink(resize_amount);
897+
if (resize_bytes != 0) {
898+
resize_heap(resize_bytes, should_expand);
894899
}
895900
}
896901

902+
void G1CollectedHeap::resize_heap_after_young_collection(size_t allocation_word_size) {
903+
Ticks start = Ticks::now();
904+
905+
bool should_expand;
906+
907+
size_t resize_bytes = _heap_sizing_policy->young_collection_resize_amount(should_expand, allocation_word_size);
908+
909+
if (resize_bytes != 0) {
910+
resize_heap(resize_bytes, should_expand);
911+
}
912+
913+
phase_times()->record_resize_heap_time((Ticks::now() - start).seconds() * 1000.0);
914+
}
915+
897916
HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
898917
bool do_gc,
899918
bool maximal_compaction,
@@ -1002,22 +1021,22 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
10021021
}
10031022

10041023
bool G1CollectedHeap::expand(size_t expand_bytes, WorkerThreads* pretouch_workers) {
1024+
assert(expand_bytes > 0, "precondition");
1025+
10051026
size_t aligned_expand_bytes = os::align_up_vm_page_size(expand_bytes);
10061027
aligned_expand_bytes = align_up(aligned_expand_bytes, G1HeapRegion::GrainBytes);
10071028

1008-
log_debug(gc, ergo, heap)("Expand the heap. requested expansion amount: %zuB expansion amount: %zuB",
1009-
expand_bytes, aligned_expand_bytes);
1029+
uint num_regions_to_expand = (uint)(aligned_expand_bytes / G1HeapRegion::GrainBytes);
1030+
1031+
log_debug(gc, ergo, heap)("Heap resize. Requested expansion amount: %zuB aligned expansion amount: %zuB (%u regions)",
1032+
expand_bytes, aligned_expand_bytes, num_regions_to_expand);
10101033

10111034
if (num_inactive_regions() == 0) {
1012-
log_debug(gc, ergo, heap)("Did not expand the heap (heap already fully expanded)");
1035+
log_debug(gc, ergo, heap)("Heap resize. Did not expand the heap (heap already fully expanded)");
10131036
return false;
10141037
}
10151038

1016-
uint regions_to_expand = (uint)(aligned_expand_bytes / G1HeapRegion::GrainBytes);
1017-
assert(regions_to_expand > 0, "Must expand by at least one region");
1018-
1019-
uint expanded_by = _hrm.expand_by(regions_to_expand, pretouch_workers);
1020-
assert(expanded_by > 0, "must have failed during commit.");
1039+
uint expanded_by = _hrm.expand_by(num_regions_to_expand, pretouch_workers);
10211040

10221041
size_t actual_expand_bytes = expanded_by * G1HeapRegion::GrainBytes;
10231042
assert(actual_expand_bytes <= aligned_expand_bytes, "post-condition");
@@ -1040,24 +1059,45 @@ bool G1CollectedHeap::expand_single_region(uint node_index) {
10401059
}
10411060

10421061
void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
1043-
size_t aligned_shrink_bytes = os::align_down_vm_page_size(shrink_bytes);
1044-
aligned_shrink_bytes = align_down(aligned_shrink_bytes, G1HeapRegion::GrainBytes);
1062+
assert(shrink_bytes > 0, "must be");
1063+
assert(is_aligned(shrink_bytes, G1HeapRegion::GrainBytes),
1064+
"Shrink request for %zuB not aligned to heap region size %zuB",
1065+
shrink_bytes, G1HeapRegion::GrainBytes);
1066+
10451067
uint num_regions_to_remove = (uint)(shrink_bytes / G1HeapRegion::GrainBytes);
10461068

10471069
uint num_regions_removed = _hrm.shrink_by(num_regions_to_remove);
10481070
size_t shrunk_bytes = num_regions_removed * G1HeapRegion::GrainBytes;
10491071

1050-
log_debug(gc, ergo, heap)("Shrink the heap. requested shrinking amount: %zuB aligned shrinking amount: %zuB actual amount shrunk: %zuB",
1051-
shrink_bytes, aligned_shrink_bytes, shrunk_bytes);
1072+
log_debug(gc, ergo, heap)("Heap resize. Requested shrinking amount: %zuB actual shrinking amount: %zuB (%u regions)",
1073+
shrink_bytes, shrunk_bytes, num_regions_removed);
10521074
if (num_regions_removed > 0) {
1053-
log_debug(gc, heap)("Uncommittable regions after shrink: %u", num_regions_removed);
10541075
policy()->record_new_heap_size(num_committed_regions());
10551076
} else {
1056-
log_debug(gc, ergo, heap)("Did not shrink the heap (heap shrinking operation failed)");
1077+
log_debug(gc, ergo, heap)("Heap resize. Did not shrink the heap (heap shrinking operation failed)");
10571078
}
10581079
}
10591080

10601081
void G1CollectedHeap::shrink(size_t shrink_bytes) {
1082+
if (capacity() == min_capacity()) {
1083+
log_debug(gc, ergo, heap)("Heap resize. Did not shrink the heap (heap already at minimum)");
1084+
return;
1085+
}
1086+
1087+
size_t aligned_shrink_bytes = os::align_down_vm_page_size(shrink_bytes);
1088+
aligned_shrink_bytes = align_down(aligned_shrink_bytes, G1HeapRegion::GrainBytes);
1089+
1090+
aligned_shrink_bytes = capacity() - MAX2(capacity() - aligned_shrink_bytes, min_capacity());
1091+
assert(is_aligned(aligned_shrink_bytes, G1HeapRegion::GrainBytes), "Bytes to shrink %zuB not aligned", aligned_shrink_bytes);
1092+
1093+
log_debug(gc, ergo, heap)("Heap resize. Requested shrink amount: %zuB aligned shrink amount: %zuB",
1094+
shrink_bytes, aligned_shrink_bytes);
1095+
1096+
if (aligned_shrink_bytes == 0) {
1097+
log_debug(gc, ergo, heap)("Heap resize. Did not shrink the heap (shrink request too small)");
1098+
return;
1099+
}
1100+
10611101
_verifier->verify_region_sets_optional();
10621102

10631103
// We should only reach here at the end of a Full GC or during Remark which
@@ -1069,7 +1109,7 @@ void G1CollectedHeap::shrink(size_t shrink_bytes) {
10691109
// could instead use the remove_all_pending() method on free_list to
10701110
// remove only the ones that we need to remove.
10711111
_hrm.remove_all_free_regions();
1072-
shrink_helper(shrink_bytes);
1112+
shrink_helper(aligned_shrink_bytes);
10731113
rebuild_region_sets(true /* free_list_only */);
10741114

10751115
_hrm.verify_optional();
@@ -1338,7 +1378,7 @@ jint G1CollectedHeap::initialize() {
13381378
}
13391379

13401380
os::trace_page_sizes("Heap",
1341-
MinHeapSize,
1381+
min_capacity(),
13421382
reserved_byte_size,
13431383
heap_rs.base(),
13441384
heap_rs.size(),
@@ -2024,7 +2064,7 @@ bool G1CollectedHeap::block_is_obj(const HeapWord* addr) const {
20242064
}
20252065

20262066
size_t G1CollectedHeap::tlab_capacity(Thread* ignored) const {
2027-
return (_policy->young_list_target_length() - _survivor.length()) * G1HeapRegion::GrainBytes;
2067+
return eden_target_length() * G1HeapRegion::GrainBytes;
20282068
}
20292069

20302070
size_t G1CollectedHeap::tlab_used(Thread* ignored) const {
@@ -2045,6 +2085,10 @@ size_t G1CollectedHeap::max_capacity() const {
20452085
return max_num_regions() * G1HeapRegion::GrainBytes;
20462086
}
20472087

2088+
size_t G1CollectedHeap::min_capacity() const {
2089+
return MinHeapSize;
2090+
}
2091+
20482092
void G1CollectedHeap::prepare_for_verify() {
20492093
_verifier->prepare_for_verify();
20502094
}
@@ -2390,24 +2434,11 @@ void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType
23902434
phase_times()->record_verify_after_time_ms((Ticks::now() - start).seconds() * MILLIUNITS);
23912435
}
23922436

2393-
void G1CollectedHeap::expand_heap_after_young_collection(){
2394-
size_t expand_bytes = _heap_sizing_policy->young_collection_expansion_amount();
2395-
if (expand_bytes > 0) {
2396-
// No need for an ergo logging here,
2397-
// expansion_amount() does this when it returns a value > 0.
2398-
Ticks expand_start = Ticks::now();
2399-
if (expand(expand_bytes, _workers)) {
2400-
double expand_ms = (Ticks::now() - expand_start).seconds() * MILLIUNITS;
2401-
phase_times()->record_expand_heap_time(expand_ms);
2402-
}
2403-
}
2404-
}
2405-
2406-
void G1CollectedHeap::do_collection_pause_at_safepoint() {
2437+
void G1CollectedHeap::do_collection_pause_at_safepoint(size_t allocation_word_size) {
24072438
assert_at_safepoint_on_vm_thread();
24082439
guarantee(!is_stw_gc_active(), "collection is not reentrant");
24092440

2410-
do_collection_pause_at_safepoint_helper();
2441+
do_collection_pause_at_safepoint_helper(allocation_word_size);
24112442
}
24122443

24132444
G1HeapPrinterMark::G1HeapPrinterMark(G1CollectedHeap* g1h) : _g1h(g1h), _heap_transition(g1h) {
@@ -2471,7 +2502,7 @@ void G1CollectedHeap::flush_region_pin_cache() {
24712502
}
24722503
}
24732504

2474-
void G1CollectedHeap::do_collection_pause_at_safepoint_helper() {
2505+
void G1CollectedHeap::do_collection_pause_at_safepoint_helper(size_t allocation_word_size) {
24752506
ResourceMark rm;
24762507

24772508
IsSTWGCActiveMark active_gc_mark;
@@ -2489,7 +2520,7 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper() {
24892520
bool should_start_concurrent_mark_operation = collector_state()->in_concurrent_start_gc();
24902521

24912522
// Perform the collection.
2492-
G1YoungCollector collector(gc_cause());
2523+
G1YoungCollector collector(gc_cause(), allocation_word_size);
24932524
collector.collect();
24942525

24952526
// It should now be safe to tell the concurrent mark thread to start
@@ -2611,6 +2642,13 @@ void G1CollectedHeap::set_young_gen_card_set_stats(const G1MonotonicArenaMemoryS
26112642

26122643
void G1CollectedHeap::record_obj_copy_mem_stats() {
26132644
size_t total_old_allocated = _old_evac_stats.allocated() + _old_evac_stats.direct_allocated();
2645+
uint total_allocated = _survivor_evac_stats.regions_filled() + _old_evac_stats.regions_filled();
2646+
2647+
log_debug(gc)("Allocated %u survivor %u old percent total %1.2f%% (%u%%)",
2648+
_survivor_evac_stats.regions_filled(), _old_evac_stats.regions_filled(),
2649+
percent_of(total_allocated, num_committed_regions() - total_allocated),
2650+
G1ReservePercent);
2651+
26142652
policy()->old_gen_alloc_tracker()->
26152653
add_allocated_bytes_since_last_gc(total_old_allocated * HeapWordSize);
26162654

src/hotspot/share/gc/g1/g1CollectedHeap.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ class G1CollectedHeap : public CollectedHeap {
473473
void retire_gc_alloc_region(G1HeapRegion* alloc_region,
474474
size_t allocated_bytes, G1HeapRegionAttr dest);
475475

476+
void resize_heap(size_t resize_bytes, bool should_expand);
477+
476478
// - if clear_all_soft_refs is true, all soft references should be
477479
// cleared during the GC.
478480
// - if do_maximal_compaction is true, full gc will do a maximally
@@ -558,7 +560,8 @@ class G1CollectedHeap : public CollectedHeap {
558560
void pin_object(JavaThread* thread, oop obj) override;
559561
void unpin_object(JavaThread* thread, oop obj) override;
560562

561-
void resize_heap_if_necessary(size_t allocation_word_size);
563+
void resize_heap_after_young_collection(size_t allocation_word_size);
564+
void resize_heap_after_full_collection(size_t allocation_word_size);
562565

563566
// Check if there is memory to uncommit and if so schedule a task to do it.
564567
void uncommit_regions_if_necessary();
@@ -743,11 +746,11 @@ class G1CollectedHeap : public CollectedHeap {
743746
// followed by a by-policy upgrade to a full collection.
744747
// precondition: at safepoint on VM thread
745748
// precondition: !is_stw_gc_active()
746-
void do_collection_pause_at_safepoint();
749+
void do_collection_pause_at_safepoint(size_t allocation_word_size = 0);
747750

748751
// Helper for do_collection_pause_at_safepoint, containing the guts
749752
// of the incremental collection pause, executed by the vm thread.
750-
void do_collection_pause_at_safepoint_helper();
753+
void do_collection_pause_at_safepoint_helper(size_t allocation_word_size);
751754

752755
void verify_before_young_collection(G1HeapVerifier::G1VerifyType type);
753756
void verify_after_young_collection(G1HeapVerifier::G1VerifyType type);
@@ -764,8 +767,6 @@ class G1CollectedHeap : public CollectedHeap {
764767
// Must be called before any decision based on pin counts.
765768
void flush_region_pin_cache();
766769

767-
void expand_heap_after_young_collection();
768-
// Update object copying statistics.
769770
void record_obj_copy_mem_stats();
770771

771772
private:
@@ -1022,6 +1023,8 @@ class G1CollectedHeap : public CollectedHeap {
10221023

10231024
void start_concurrent_gc_for_metadata_allocation(GCCause::Cause gc_cause);
10241025

1026+
bool last_gc_was_periodic() { return _gc_lastcause == GCCause::_g1_periodic_collection; }
1027+
10251028
void remove_from_old_gen_sets(const uint old_regions_removed,
10261029
const uint humongous_regions_removed);
10271030
void prepend_to_freelist(G1FreeRegionList* list);
@@ -1190,6 +1193,7 @@ class G1CollectedHeap : public CollectedHeap {
11901193

11911194
// Print the maximum heap capacity.
11921195
size_t max_capacity() const override;
1196+
size_t min_capacity() const;
11931197

11941198
Tickspan time_since_last_collection() const { return Ticks::now() - _collection_pause_end; }
11951199

@@ -1204,6 +1208,7 @@ class G1CollectedHeap : public CollectedHeap {
12041208

12051209
G1SurvivorRegions* survivor() { return &_survivor; }
12061210

1211+
inline uint eden_target_length() const;
12071212
uint eden_regions_count() const { return _eden.length(); }
12081213
uint eden_regions_count(uint node_index) const { return _eden.regions_on_node(node_index); }
12091214
uint survivor_regions_count() const { return _survivor.length(); }

src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -316,4 +316,8 @@ inline bool G1CollectedHeap::is_collection_set_candidate(const G1HeapRegion* r)
316316
return candidates->contains(r);
317317
}
318318

319+
inline uint G1CollectedHeap::eden_target_length() const {
320+
return _policy->young_list_target_length() - survivor_regions_count();
321+
}
322+
319323
#endif // SHARE_GC_G1_G1COLLECTEDHEAP_INLINE_HPP

src/hotspot/share/gc/g1/g1ConcurrentMark.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,8 +1450,13 @@ void G1ConcurrentMark::remark() {
14501450
// GC pause.
14511451
_g1h->increment_total_collections();
14521452

1453-
_g1h->resize_heap_if_necessary(size_t(0) /* allocation_word_size */);
1454-
_g1h->uncommit_regions_if_necessary();
1453+
// For Remark Pauses that may have been triggered by PeriodicGCs, we maintain
1454+
// resizing based on MinHeapFreeRatio or MaxHeapFreeRatio. If a PeriodicGC is
1455+
// triggered, it likely means there are very few regular GCs, making resizing
1456+
// based on gc heuristics less effective.
1457+
if (_g1h->last_gc_was_periodic()) {
1458+
_g1h->resize_heap_after_full_collection(0 /* allocation_word_size */);
1459+
}
14551460

14561461
compute_new_sizes();
14571462

src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ void G1GCPhaseTimes::reset() {
178178
_cur_pre_evacuate_prepare_time_ms = 0.0;
179179
_cur_post_evacuate_cleanup_1_time_ms = 0.0;
180180
_cur_post_evacuate_cleanup_2_time_ms = 0.0;
181-
_cur_expand_heap_time_ms = 0.0;
181+
_cur_resize_heap_time_ms = 0.0;
182182
_cur_ref_proc_time_ms = 0.0;
183183
_cur_collection_start_sec = 0.0;
184184
_root_region_scan_wait_time_ms = 0.0;
@@ -488,7 +488,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set(bool evacuation_failed
488488
_cur_post_evacuate_cleanup_2_time_ms +
489489
_recorded_total_rebuild_freelist_time_ms +
490490
_recorded_prepare_for_mutator_time_ms +
491-
_cur_expand_heap_time_ms;
491+
_cur_resize_heap_time_ms;
492492

493493
info_time("Post Evacuate Collection Set", sum_ms);
494494

@@ -537,7 +537,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set(bool evacuation_failed
537537
trace_phase(_gc_par_phases[RebuildFreeList]);
538538

539539
debug_time("Prepare For Mutator", _recorded_prepare_for_mutator_time_ms);
540-
debug_time("Expand Heap After Collection", _cur_expand_heap_time_ms);
540+
debug_time("Resize Heap After Collection", _cur_resize_heap_time_ms);
541541

542542
return sum_ms;
543543
}

0 commit comments

Comments
 (0)