Skip to content

Commit f0e7066

Browse files
author
Thomas Schatzl
committed
8364414: G1: Use simpler data structure for holding collection set candidates during calculation
Reviewed-by: ayang, iwalulya
1 parent 9439d76 commit f0e7066

File tree

4 files changed

+57
-66
lines changed

4 files changed

+57
-66
lines changed

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

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ G1CSetCandidateGroup::G1CSetCandidateGroup() :
4444

4545
void G1CSetCandidateGroup::add(G1HeapRegion* hr) {
4646
G1CollectionSetCandidateInfo c(hr);
47-
add(c);
48-
}
49-
50-
void G1CSetCandidateGroup::add(G1CollectionSetCandidateInfo& hr_info) {
51-
G1HeapRegion* hr = hr_info._r;
52-
_candidates.append(hr_info);
47+
_candidates.append(c);
5348
hr->install_cset_group(this);
5449
}
5550

@@ -133,31 +128,6 @@ int G1CSetCandidateGroup::compare_gc_efficiency(G1CSetCandidateGroup** gr1, G1CS
133128
}
134129
}
135130

136-
int G1CollectionSetCandidateInfo::compare_region_gc_efficiency(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2) {
137-
// Make sure that null entries are moved to the end.
138-
if (ci1->_r == nullptr) {
139-
if (ci2->_r == nullptr) {
140-
return 0;
141-
} else {
142-
return 1;
143-
}
144-
} else if (ci2->_r == nullptr) {
145-
return -1;
146-
}
147-
148-
G1Policy* p = G1CollectedHeap::heap()->policy();
149-
double gc_efficiency1 = p->predict_gc_efficiency(ci1->_r);
150-
double gc_efficiency2 = p->predict_gc_efficiency(ci2->_r);
151-
152-
if (gc_efficiency1 > gc_efficiency2) {
153-
return -1;
154-
} else if (gc_efficiency1 < gc_efficiency2) {
155-
return 1;
156-
} else {
157-
return 0;
158-
}
159-
}
160-
161131
G1CSetCandidateGroupList::G1CSetCandidateGroupList() : _groups(8, mtGC), _num_regions(0) { }
162132

163133
void G1CSetCandidateGroupList::append(G1CSetCandidateGroup* group) {
@@ -279,9 +249,9 @@ void G1CollectionSetCandidates::sort_marking_by_efficiency() {
279249
_from_marking_groups.verify();
280250
}
281251

282-
void G1CollectionSetCandidates::set_candidates_from_marking(G1CollectionSetCandidateInfo* candidate_infos,
283-
uint num_infos) {
284-
if (num_infos == 0) {
252+
void G1CollectionSetCandidates::set_candidates_from_marking(G1HeapRegion** candidates,
253+
uint num_candidates) {
254+
if (num_candidates == 0) {
285255
log_debug(gc, ergo, cset) ("No regions selected from marking.");
286256
return;
287257
}
@@ -294,7 +264,7 @@ void G1CollectionSetCandidates::set_candidates_from_marking(G1CollectionSetCandi
294264
// the G1MixedGCCountTarget. For the first collection in a Mixed GC cycle, we can add all regions
295265
// required to meet this threshold to the same remset group. We are certain these will be collected in
296266
// the same MixedGC.
297-
uint group_limit = p->calc_min_old_cset_length(num_infos);
267+
uint group_limit = p->calc_min_old_cset_length(num_candidates);
298268

299269
uint num_added_to_group = 0;
300270

@@ -303,8 +273,8 @@ void G1CollectionSetCandidates::set_candidates_from_marking(G1CollectionSetCandi
303273

304274
current = new G1CSetCandidateGroup();
305275

306-
for (uint i = 0; i < num_infos; i++) {
307-
G1HeapRegion* r = candidate_infos[i]._r;
276+
for (uint i = 0; i < num_candidates; i++) {
277+
G1HeapRegion* r = candidates[i];
308278
assert(!contains(r), "must not contain region %u", r->hrm_index());
309279
_contains_map[r->hrm_index()] = CandidateOrigin::Marking;
310280

@@ -318,16 +288,16 @@ void G1CollectionSetCandidates::set_candidates_from_marking(G1CollectionSetCandi
318288
current = new G1CSetCandidateGroup();
319289
num_added_to_group = 0;
320290
}
321-
current->add(candidate_infos[i]);
291+
current->add(r);
322292
num_added_to_group++;
323293
}
324294

325295
_from_marking_groups.append(current);
326296

327-
assert(_from_marking_groups.num_regions() == num_infos, "Must be!");
297+
assert(_from_marking_groups.num_regions() == num_candidates, "Must be!");
328298

329-
log_debug(gc, ergo, cset) ("Finished creating %u collection groups from %u regions", _from_marking_groups.length(), num_infos);
330-
_last_marking_candidates_length = num_infos;
299+
log_debug(gc, ergo, cset) ("Finished creating %u collection groups from %u regions", _from_marking_groups.length(), num_candidates);
300+
_last_marking_candidates_length = num_candidates;
331301

332302
verify();
333303
}

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ struct G1CollectionSetCandidateInfo {
4848
++_num_unreclaimed;
4949
return _num_unreclaimed < G1NumCollectionsKeepPinned;
5050
}
51-
52-
static int compare_region_gc_efficiency(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2);
5351
};
5452

5553
using G1CSetCandidateGroupIterator = GrowableArrayIterator<G1CollectionSetCandidateInfo>;
@@ -91,7 +89,6 @@ class G1CSetCandidateGroup : public CHeapObj<mtGCCardSet>{
9189
}
9290

9391
void add(G1HeapRegion* hr);
94-
void add(G1CollectionSetCandidateInfo& hr_info);
9592

9693
uint length() const { return (uint)_candidates.length(); }
9794

@@ -235,10 +232,10 @@ class G1CollectionSetCandidates : public CHeapObj<mtGC> {
235232

236233
void clear();
237234

238-
// Merge collection set candidates from marking into the current marking list
235+
// Merge collection set candidates from marking into the current marking candidates
239236
// (which needs to be empty).
240-
void set_candidates_from_marking(G1CollectionSetCandidateInfo* candidate_infos,
241-
uint num_infos);
237+
void set_candidates_from_marking(G1HeapRegion** candidates,
238+
uint num_candidates);
242239
// The most recent length of the list that had been merged last via
243240
// set_candidates_from_marking(). Used for calculating minimum collection set
244241
// regions.

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

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,54 @@
3131
#include "utilities/quickSort.hpp"
3232

3333
// Determine collection set candidates (from marking): For all regions determine
34-
// whether they should be a collection set candidate, calculate their efficiency,
35-
// sort and put them into the candidates.
34+
// whether they should be a collection set candidate. Calculate their efficiency,
35+
// sort, and put them into the collection set candidates.
36+
//
3637
// Threads calculate the GC efficiency of the regions they get to process, and
3738
// put them into some work area without sorting. At the end that array is sorted and
3839
// moved to the destination.
3940
class G1BuildCandidateRegionsTask : public WorkerTask {
40-
41-
using CandidateInfo = G1CollectionSetCandidateInfo;
42-
4341
// Work area for building the set of collection set candidates. Contains references
4442
// to heap regions with their GC efficiencies calculated. To reduce contention
4543
// on claiming array elements, worker threads claim parts of this array in chunks;
4644
// Array elements may be null as threads might not get enough regions to fill
4745
// up their chunks completely.
4846
// Final sorting will remove them.
4947
class G1BuildCandidateArray : public StackObj {
50-
5148
uint const _max_size;
5249
uint const _chunk_size;
5350

54-
CandidateInfo* _data;
51+
G1HeapRegion** _data;
5552

5653
uint volatile _cur_claim_idx;
5754

55+
static int compare_region_gc_efficiency(G1HeapRegion** rr1, G1HeapRegion** rr2) {
56+
G1HeapRegion* r1 = *rr1;
57+
G1HeapRegion* r2 = *rr2;
58+
// Make sure that null entries are moved to the end.
59+
if (r1 == nullptr) {
60+
if (r2 == nullptr) {
61+
return 0;
62+
} else {
63+
return 1;
64+
}
65+
} else if (r2 == nullptr) {
66+
return -1;
67+
}
68+
69+
G1Policy* p = G1CollectedHeap::heap()->policy();
70+
double gc_efficiency1 = p->predict_gc_efficiency(r1);
71+
double gc_efficiency2 = p->predict_gc_efficiency(r2);
72+
73+
if (gc_efficiency1 > gc_efficiency2) {
74+
return -1;
75+
} else if (gc_efficiency1 < gc_efficiency2) {
76+
return 1;
77+
} else {
78+
return 0;
79+
}
80+
}
81+
5882
// Calculates the maximum array size that will be used.
5983
static uint required_array_size(uint num_regions, uint chunk_size, uint num_workers) {
6084
uint const max_waste = num_workers * chunk_size;
@@ -68,15 +92,15 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
6892
G1BuildCandidateArray(uint max_num_regions, uint chunk_size, uint num_workers) :
6993
_max_size(required_array_size(max_num_regions, chunk_size, num_workers)),
7094
_chunk_size(chunk_size),
71-
_data(NEW_C_HEAP_ARRAY(CandidateInfo, _max_size, mtGC)),
95+
_data(NEW_C_HEAP_ARRAY(G1HeapRegion*, _max_size, mtGC)),
7296
_cur_claim_idx(0) {
7397
for (uint i = 0; i < _max_size; i++) {
74-
_data[i] = CandidateInfo();
98+
_data[i] = nullptr;
7599
}
76100
}
77101

78102
~G1BuildCandidateArray() {
79-
FREE_C_HEAP_ARRAY(CandidateInfo, _data);
103+
FREE_C_HEAP_ARRAY(G1HeapRegion*, _data);
80104
}
81105

82106
// Claim a new chunk, returning its bounds [from, to[.
@@ -92,24 +116,24 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
92116
// Set element in array.
93117
void set(uint idx, G1HeapRegion* hr) {
94118
assert(idx < _max_size, "Index %u out of bounds %u", idx, _max_size);
95-
assert(_data[idx]._r == nullptr, "Value must not have been set.");
96-
_data[idx] = CandidateInfo(hr);
119+
assert(_data[idx] == nullptr, "Value must not have been set.");
120+
_data[idx] = hr;
97121
}
98122

99123
void sort_by_gc_efficiency() {
100124
if (_cur_claim_idx == 0) {
101125
return;
102126
}
103127
for (uint i = _cur_claim_idx; i < _max_size; i++) {
104-
assert(_data[i]._r == nullptr, "must be");
128+
assert(_data[i] == nullptr, "must be");
105129
}
106-
qsort(_data, _cur_claim_idx, sizeof(_data[0]), (_sort_Fn)G1CollectionSetCandidateInfo::compare_region_gc_efficiency);
130+
qsort(_data, _cur_claim_idx, sizeof(_data[0]), (_sort_Fn)compare_region_gc_efficiency);
107131
for (uint i = _cur_claim_idx; i < _max_size; i++) {
108-
assert(_data[i]._r == nullptr, "must be");
132+
assert(_data[i] == nullptr, "must be");
109133
}
110134
}
111135

112-
CandidateInfo* array() const { return _data; }
136+
G1HeapRegion** array() const { return _data; }
113137
};
114138

115139
// Per-region closure. In addition to determining whether a region should be
@@ -193,7 +217,7 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
193217
// available (for forward progress in evacuation) or the waste accumulated by the
194218
// removed regions is above the maximum allowed waste.
195219
// Updates number of candidates and reclaimable bytes given.
196-
void prune(CandidateInfo* data) {
220+
void prune(G1HeapRegion** data) {
197221
G1Policy* p = G1CollectedHeap::heap()->policy();
198222

199223
uint num_candidates = Atomic::load(&_num_regions_added);
@@ -211,7 +235,7 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
211235
uint max_to_prune = num_candidates - min_old_cset_length;
212236

213237
while (true) {
214-
G1HeapRegion* r = data[num_candidates - num_pruned - 1]._r;
238+
G1HeapRegion* r = data[num_candidates - num_pruned - 1];
215239
size_t const reclaimable = r->reclaimable_bytes();
216240
if (num_pruned >= max_to_prune ||
217241
wasted_bytes + reclaimable > allowed_waste) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ class WorkerThreads;
3838
class G1CollectionSetChooser : public AllStatic {
3939
static uint calculate_work_chunk_size(uint num_workers, uint num_regions);
4040

41-
public:
4241
static size_t mixed_gc_live_threshold_bytes() {
4342
return G1HeapRegion::GrainBytes * (size_t)G1MixedGCLiveThresholdPercent / 100;
4443
}
4544

45+
public:
4646
static bool region_occupancy_low_enough_for_evac(size_t live_bytes) {
4747
return live_bytes < mixed_gc_live_threshold_bytes();
4848
}

0 commit comments

Comments
 (0)