Skip to content

Commit d9e40dd

Browse files
author
Ivan Walulya
committed
8199407: Skip Rebuild Remset Phase if there are no rebuild candidates
Reviewed-by: tschatzl, sjohanss
1 parent 8dbf7aa commit d9e40dd

File tree

5 files changed

+123
-10
lines changed

5 files changed

+123
-10
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,8 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h,
410410
_max_concurrent_workers(0),
411411

412412
_region_mark_stats(NEW_C_HEAP_ARRAY(G1RegionMarkStats, _g1h->max_reserved_regions(), mtGC)),
413-
_top_at_rebuild_starts(NEW_C_HEAP_ARRAY(HeapWord*, _g1h->max_reserved_regions(), mtGC))
413+
_top_at_rebuild_starts(NEW_C_HEAP_ARRAY(HeapWord*, _g1h->max_reserved_regions(), mtGC)),
414+
_needs_remembered_set_rebuild(false)
414415
{
415416
assert(CGC_lock != NULL, "CGC_lock must be initialized");
416417

@@ -1150,6 +1151,8 @@ void G1ConcurrentMark::remark() {
11501151

11511152
log_debug(gc, remset, tracking)("Remembered Set Tracking update regions total %u, selected %u",
11521153
_g1h->num_regions(), cl.total_selected_for_rebuild());
1154+
1155+
_needs_remembered_set_rebuild = (cl.total_selected_for_rebuild() > 0);
11531156
}
11541157
{
11551158
GCTraceTime(Debug, gc, phases) debug("Reclaim Empty Regions", _gc_timer_cm);
@@ -1321,10 +1324,12 @@ void G1ConcurrentMark::cleanup() {
13211324

13221325
verify_during_pause(G1HeapVerifier::G1VerifyCleanup, VerifyOption_G1UsePrevMarking, "Cleanup before");
13231326

1324-
{
1327+
if (needs_remembered_set_rebuild()) {
13251328
GCTraceTime(Debug, gc, phases) debug("Update Remembered Set Tracking After Rebuild", _gc_timer_cm);
13261329
G1UpdateRemSetTrackingAfterRebuild cl(_g1h);
13271330
_g1h->heap_region_iterate(&cl);
1331+
} else {
1332+
log_debug(gc, phases)("No Remembered Sets to update after rebuild");
13281333
}
13291334

13301335
verify_during_pause(G1HeapVerifier::G1VerifyCleanup, VerifyOption_G1UsePrevMarking, "Cleanup after");
@@ -1340,7 +1345,7 @@ void G1ConcurrentMark::cleanup() {
13401345

13411346
{
13421347
GCTraceTime(Debug, gc, phases) debug("Finalize Concurrent Mark Cleanup", _gc_timer_cm);
1343-
policy->record_concurrent_mark_cleanup_end();
1348+
policy->record_concurrent_mark_cleanup_end(needs_remembered_set_rebuild());
13441349
}
13451350
}
13461351

@@ -1953,6 +1958,12 @@ void G1ConcurrentMark::verify_no_collection_set_oops() {
19531958
#endif // PRODUCT
19541959

19551960
void G1ConcurrentMark::rebuild_rem_set_concurrently() {
1961+
// If Remark did not select any regions for RemSet rebuild,
1962+
// skip the rebuild remembered set phase
1963+
if (!needs_remembered_set_rebuild()) {
1964+
log_debug(gc, marking)("Skipping Remembered Set Rebuild. No regions selected for rebuild");
1965+
return;
1966+
}
19561967
_g1h->rem_set()->rebuild_rem_set(this, _concurrent_workers, _worker_id_offset);
19571968
}
19581969

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
457457
// means that this region does not be scanned during the rebuilding remembered
458458
// set phase at all.
459459
HeapWord* volatile* _top_at_rebuild_starts;
460+
// True when Remark pause selected regions for rebuilding.
461+
bool _needs_remembered_set_rebuild;
460462
public:
461463
void add_to_liveness(uint worker_id, oop const obj, size_t size);
462464
// Live words in the given region as determined by concurrent marking, i.e. the amount of
@@ -597,6 +599,9 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
597599
private:
598600
// Rebuilds the remembered sets for chosen regions in parallel and concurrently to the application.
599601
void rebuild_rem_set_concurrently();
602+
603+
uint needs_remembered_set_rebuild() const { return _needs_remembered_set_rebuild; }
604+
600605
};
601606

602607
// A class representing a marking task.

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,6 @@ void G1Policy::record_concurrent_mark_remark_end() {
549549
double end_time_sec = os::elapsedTime();
550550
double elapsed_time_ms = (end_time_sec - _mark_remark_start_sec)*1000.0;
551551
_analytics->report_concurrent_mark_remark_times_ms(elapsed_time_ms);
552-
553552
record_pause(G1GCPauseType::Remark, _mark_remark_start_sec, end_time_sec);
554553
}
555554

@@ -1098,16 +1097,19 @@ void G1Policy::decide_on_conc_mark_initiation() {
10981097
}
10991098
}
11001099

1101-
void G1Policy::record_concurrent_mark_cleanup_end() {
1102-
G1CollectionSetCandidates* candidates = G1CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions());
1103-
_collection_set->set_candidates(candidates);
1100+
void G1Policy::record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_sets) {
1101+
bool mixed_gc_pending = false;
1102+
if (has_rebuilt_remembered_sets) {
1103+
G1CollectionSetCandidates* candidates = G1CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions());
1104+
_collection_set->set_candidates(candidates);
1105+
mixed_gc_pending = next_gc_should_be_mixed("request mixed gcs", "request young-only gcs");
1106+
}
11041107

11051108
if (log_is_enabled(Trace, gc, liveness)) {
11061109
G1PrintRegionLivenessInfoClosure cl("Post-Cleanup");
11071110
_g1h->heap_region_iterate(&cl);
11081111
}
11091112

1110-
bool mixed_gc_pending = next_gc_should_be_mixed("request mixed gcs", "request young-only gcs");
11111113
if (!mixed_gc_pending) {
11121114
clear_collection_set_candidates();
11131115
abort_time_to_mixed_tracking();
@@ -1134,6 +1136,9 @@ class G1ClearCollectionSetCandidateRemSets : public HeapRegionClosure {
11341136
};
11351137

11361138
void G1Policy::clear_collection_set_candidates() {
1139+
if (_collection_set->candidates() == NULL) {
1140+
return;
1141+
}
11371142
// Clear remembered sets of remaining candidate regions and the actual candidate
11381143
// set.
11391144
G1ClearCollectionSetCandidateRemSets cl;
@@ -1229,7 +1234,7 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str,
12291234
const char* false_action_str) const {
12301235
G1CollectionSetCandidates* candidates = _collection_set->candidates();
12311236

1232-
if (candidates->is_empty()) {
1237+
if (candidates == NULL || candidates->is_empty()) {
12331238
log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str);
12341239
return false;
12351240
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ class G1Policy: public CHeapObj<mtGC> {
321321

322322
// Record start, end, and completion of cleanup.
323323
void record_concurrent_mark_cleanup_start();
324-
void record_concurrent_mark_cleanup_end();
324+
void record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_sets);
325325

326326
void print_phases();
327327

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
package gc.g1;
25+
26+
/*
27+
* @test TestSkipRebuildRemsetPhase
28+
* @summary Skip Rebuild Remset Phase if the Remark pause does not identify any rebuild candidates.
29+
* Fill up a region to above the set G1MixedGCLiveThresholdPercent.
30+
* @requires vm.gc.G1
31+
* @library /test/lib
32+
* @build sun.hotspot.WhiteBox
33+
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
34+
* @run driver gc.g1.TestSkipRebuildRemsetPhase
35+
*/
36+
37+
import java.util.regex.Pattern;
38+
import java.util.regex.Matcher;
39+
40+
import jdk.test.lib.process.OutputAnalyzer;
41+
import jdk.test.lib.process.ProcessTools;
42+
import jdk.test.lib.Asserts;
43+
import sun.hotspot.WhiteBox;
44+
45+
public class TestSkipRebuildRemsetPhase {
46+
public static void main(String[] args) throws Exception {
47+
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:.",
48+
"-XX:+UseG1GC",
49+
"-XX:+UnlockExperimentalVMOptions",
50+
"-XX:+UnlockDiagnosticVMOptions",
51+
"-XX:+WhiteBoxAPI",
52+
"-XX:G1MixedGCLiveThresholdPercent=20",
53+
"-Xlog:gc+marking=debug,gc+phases=debug,gc+remset+tracking=trace",
54+
"-Xms10M",
55+
"-Xmx10M",
56+
GCTest.class.getName());
57+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
58+
output.shouldContain("Skipping Remembered Set Rebuild.");
59+
output.shouldContain("No Remembered Sets to update after rebuild");
60+
output.shouldHaveExitValue(0);
61+
}
62+
63+
public static class GCTest {
64+
public static void main(String args[]) throws Exception {
65+
WhiteBox wb = WhiteBox.getWhiteBox();
66+
// Allocate some memory less than region size.
67+
Object used = alloc();
68+
69+
// Trigger the full GC using the WhiteBox API.
70+
wb.fullGC(); // full
71+
72+
// Memory objects have been promoted to old by full GC.
73+
// Concurrent cycle should not select any regions for rebuilding
74+
wb.g1StartConcMarkCycle(); // concurrent-start, remark and cleanup
75+
76+
// Sleep to make sure concurrent cycle is done
77+
while (wb.g1InConcurrentMark()) {
78+
Thread.sleep(1000);
79+
}
80+
81+
System.out.println(used);
82+
}
83+
84+
private static Object alloc() {
85+
// Since G1MixedGCLiveThresholdPercent is 20%, make sure to allocate object larger than that
86+
// so that it will not be collected and the expected message printed.
87+
final int objectSize = WhiteBox.getWhiteBox().g1RegionSize() / 3;
88+
Object ret = new byte[objectSize];
89+
return ret;
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)