42
43 CollectionSetChooser* G1CollectionSet::cset_chooser() {
44 return _cset_chooser;
45 }
46
47 double G1CollectionSet::predict_region_elapsed_time_ms(HeapRegion* hr) {
48 return _policy->predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
49 }
50
51
52 G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h) :
53 _g1(g1h),
54 _policy(NULL),
55 _cset_chooser(new CollectionSetChooser()),
56 _eden_region_length(0),
57 _survivor_region_length(0),
58 _old_region_length(0),
59
60 _head(NULL),
61 _bytes_used_before(0),
62 _bytes_live_before(0),
63 _recorded_rs_lengths(0),
64 // Incremental CSet attributes
65 _inc_build_state(Inactive),
66 _inc_head(NULL),
67 _inc_tail(NULL),
68 _inc_bytes_used_before(0),
69 _inc_bytes_live_before(0),
70 _inc_recorded_rs_lengths(0),
71 _inc_recorded_rs_lengths_diffs(0),
72 _inc_predicted_elapsed_time_ms(0.0),
73 _inc_predicted_elapsed_time_ms_diffs(0.0) {}
74
75 G1CollectionSet::~G1CollectionSet() {
76 delete _cset_chooser;
77 }
78
79 void G1CollectionSet::init_region_lengths(uint eden_cset_region_length,
80 uint survivor_cset_region_length) {
81 _eden_region_length = eden_cset_region_length;
82 _survivor_region_length = survivor_cset_region_length;
83 _old_region_length = 0;
84 }
85
86 void G1CollectionSet::set_recorded_rs_lengths(size_t rs_lengths) {
87 _recorded_rs_lengths = rs_lengths;
88 }
89
90 // Add the heap region at the head of the non-incremental collection set
91 void G1CollectionSet::add_old_region(HeapRegion* hr) {
92 assert(_inc_build_state == Active, "Precondition");
93 assert(hr->is_old(), "the region should be old");
94
95 assert(!hr->in_collection_set(), "should not already be in the CSet");
96 _g1->register_old_region_with_cset(hr);
97 hr->set_next_in_collection_set(_head);
98 _head = hr;
99 _bytes_used_before += hr->used();
100 _bytes_live_before += hr->live_bytes();
101 size_t rs_length = hr->rem_set()->occupied();
102 _recorded_rs_lengths += rs_length;
103 _old_region_length += 1;
104 }
105
106 // Initialize the per-collection-set information
107 void G1CollectionSet::start_incremental_building() {
108 assert(_inc_build_state == Inactive, "Precondition");
109
110 _inc_head = NULL;
111 _inc_tail = NULL;
112 _inc_bytes_used_before = 0;
113 _inc_bytes_live_before = 0;
114
115 _inc_recorded_rs_lengths = 0;
116 _inc_recorded_rs_lengths_diffs = 0;
117 _inc_predicted_elapsed_time_ms = 0.0;
118 _inc_predicted_elapsed_time_ms_diffs = 0.0;
119 _inc_build_state = Active;
120 }
121
122 void G1CollectionSet::finalize_incremental_building() {
123 assert(_inc_build_state == Active, "Precondition");
124 assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
125
126 // The two "main" fields, _inc_recorded_rs_lengths and
127 // _inc_predicted_elapsed_time_ms, are updated by the thread
128 // that adds a new region to the CSet. Further updates by the
129 // concurrent refinement thread that samples the young RSet lengths
130 // are accumulated in the *_diffs fields. Here we add the diffs to
131 // the "main" fields.
132
133 if (_inc_recorded_rs_lengths_diffs >= 0) {
196 // information in the heap region here (before the region gets added
197 // to the collection set). An individual heap region's cached values
198 // are calculated, aggregated with the policy collection set info,
199 // and cached in the heap region here (initially) and (subsequently)
200 // by the Young List sampling code.
201
202 size_t rs_length = hr->rem_set()->occupied();
203 double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr);
204
205 // Cache the values we have added to the aggregated information
206 // in the heap region in case we have to remove this region from
207 // the incremental collection set, or it is updated by the
208 // rset sampling code
209 hr->set_recorded_rs_length(rs_length);
210 hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
211
212 size_t used_bytes = hr->used();
213 _inc_recorded_rs_lengths += rs_length;
214 _inc_predicted_elapsed_time_ms += region_elapsed_time_ms;
215 _inc_bytes_used_before += used_bytes;
216 _inc_bytes_live_before += hr->live_bytes();
217
218 assert(!hr->in_collection_set(), "invariant");
219 _g1->register_young_region_with_cset(hr);
220 assert(hr->next_in_collection_set() == NULL, "invariant");
221 }
222
223 // Add the region at the RHS of the incremental cset
224 void G1CollectionSet::add_survivor_regions(HeapRegion* hr) {
225 // We should only ever be appending survivors at the end of a pause
226 assert(hr->is_survivor(), "Logic");
227
228 // Do the 'common' stuff
229 add_young_region_common(hr);
230
231 // Now add the region at the right hand side
232 if (_inc_tail == NULL) {
233 assert(_inc_head == NULL, "invariant");
234 _inc_head = hr;
235 } else {
236 _inc_tail->set_next_in_collection_set(hr);
299 uint survivor_region_length = young_list->survivor_length();
300 uint eden_region_length = young_list->eden_length();
301 init_region_lengths(eden_region_length, survivor_region_length);
302
303 HeapRegion* hr = young_list->first_survivor_region();
304 while (hr != NULL) {
305 assert(hr->is_survivor(), "badly formed young list");
306 // There is a convention that all the young regions in the CSet
307 // are tagged as "eden", so we do this for the survivors here. We
308 // use the special set_eden_pre_gc() as it doesn't check that the
309 // region is free (which is not the case here).
310 hr->set_eden_pre_gc();
311 hr = hr->get_next_young_region();
312 }
313
314 // Clear the fields that point to the survivor list - they are all young now.
315 young_list->clear_survivors();
316
317 _head = _inc_head;
318 _bytes_used_before = _inc_bytes_used_before;
319 _bytes_live_before = _inc_bytes_live_before;
320 time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
321
322 log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
323 eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms);
324
325 // The number of recorded young regions is the incremental
326 // collection set's current size
327 set_recorded_rs_lengths(_inc_recorded_rs_lengths);
328
329 double young_end_time_sec = os::elapsedTime();
330 phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
331
332 return time_remaining_ms;
333 }
334
335 void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
336 double non_young_start_time_sec = os::elapsedTime();
337 double predicted_old_time_ms = 0.0;
338
339 if (!collector_state()->gcs_are_young()) {
340 cset_chooser()->verify();
341 const uint min_old_cset_length = _policy->calc_min_old_cset_length();
342 const uint max_old_cset_length = _policy->calc_max_old_cset_length();
343 const size_t estimated_available_bytes = _policy->available_bytes_estimate();
344
345 uint expensive_region_num = 0;
346 bool check_time_remaining = _policy->adaptive_young_list_length();
347
348 HeapRegion* hr = cset_chooser()->peek();
349 while (hr != NULL) {
350 if (old_region_length() >= max_old_cset_length) {
351 // Added maximum number of old regions to the CSet.
352 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). old %u regions, max %u regions",
353 old_region_length(), max_old_cset_length);
354 break;
355 }
356
357 // Stop adding regions if the remaining reclaimable space is
358 // not above G1HeapWastePercent.
359 size_t reclaimable_bytes = cset_chooser()->remaining_reclaimable_bytes();
360 double reclaimable_perc = _policy->reclaimable_bytes_perc(reclaimable_bytes);
361 double threshold = (double) G1HeapWastePercent;
362 if (reclaimable_perc <= threshold) {
363 // We've added enough old regions that the amount of uncollected
364 // reclaimable space is at or below the waste threshold. Stop
365 // adding old regions to the CSet.
366 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
367 "old %u regions, max %u regions, reclaimable: " SIZE_FORMAT "B (%1.2f%%) threshold: " UINTX_FORMAT "%%",
368 old_region_length(), max_old_cset_length, reclaimable_bytes, reclaimable_perc, G1HeapWastePercent);
369 break;
370 }
371
372 // Stop adding regions if the live bytes (according to the last marking)
373 // added so far would exceed the estimated free bytes.
374 if ((_bytes_live_before + hr->live_bytes()) > estimated_available_bytes) {
375 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reached estimated free space limit)");
376 break;
377 }
378
379 double predicted_time_ms = predict_region_elapsed_time_ms(hr);
380 if (check_time_remaining) {
381 if (predicted_time_ms > time_remaining_ms) {
382 // Too expensive for the current CSet.
383
384 if (old_region_length() >= min_old_cset_length) {
385 // We have added the minimum number of old regions to the CSet,
386 // we are done with this CSet.
387 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high). "
388 "predicted time: %1.2fms, remaining time: %1.2fms old %u regions, min %u regions",
389 predicted_time_ms, time_remaining_ms, old_region_length(), min_old_cset_length);
390 break;
391 }
392
393 // We'll add it anyway given that we haven't reached the
394 // minimum number of old regions.
395 expensive_region_num += 1;
|
42
43 CollectionSetChooser* G1CollectionSet::cset_chooser() {
44 return _cset_chooser;
45 }
46
47 double G1CollectionSet::predict_region_elapsed_time_ms(HeapRegion* hr) {
48 return _policy->predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
49 }
50
51
52 G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h) :
53 _g1(g1h),
54 _policy(NULL),
55 _cset_chooser(new CollectionSetChooser()),
56 _eden_region_length(0),
57 _survivor_region_length(0),
58 _old_region_length(0),
59
60 _head(NULL),
61 _bytes_used_before(0),
62 _recorded_rs_lengths(0),
63 // Incremental CSet attributes
64 _inc_build_state(Inactive),
65 _inc_head(NULL),
66 _inc_tail(NULL),
67 _inc_bytes_used_before(0),
68 _inc_recorded_rs_lengths(0),
69 _inc_recorded_rs_lengths_diffs(0),
70 _inc_predicted_elapsed_time_ms(0.0),
71 _inc_predicted_elapsed_time_ms_diffs(0.0) {}
72
73 G1CollectionSet::~G1CollectionSet() {
74 delete _cset_chooser;
75 }
76
77 void G1CollectionSet::init_region_lengths(uint eden_cset_region_length,
78 uint survivor_cset_region_length) {
79 _eden_region_length = eden_cset_region_length;
80 _survivor_region_length = survivor_cset_region_length;
81 _old_region_length = 0;
82 }
83
84 void G1CollectionSet::set_recorded_rs_lengths(size_t rs_lengths) {
85 _recorded_rs_lengths = rs_lengths;
86 }
87
88 // Add the heap region at the head of the non-incremental collection set
89 void G1CollectionSet::add_old_region(HeapRegion* hr) {
90 assert(_inc_build_state == Active, "Precondition");
91 assert(hr->is_old(), "the region should be old");
92
93 assert(!hr->in_collection_set(), "should not already be in the CSet");
94 _g1->register_old_region_with_cset(hr);
95 hr->set_next_in_collection_set(_head);
96 _head = hr;
97 _bytes_used_before += hr->used();
98 size_t rs_length = hr->rem_set()->occupied();
99 _recorded_rs_lengths += rs_length;
100 _old_region_length += 1;
101 }
102
103 // Initialize the per-collection-set information
104 void G1CollectionSet::start_incremental_building() {
105 assert(_inc_build_state == Inactive, "Precondition");
106
107 _inc_head = NULL;
108 _inc_tail = NULL;
109 _inc_bytes_used_before = 0;
110
111 _inc_recorded_rs_lengths = 0;
112 _inc_recorded_rs_lengths_diffs = 0;
113 _inc_predicted_elapsed_time_ms = 0.0;
114 _inc_predicted_elapsed_time_ms_diffs = 0.0;
115 _inc_build_state = Active;
116 }
117
118 void G1CollectionSet::finalize_incremental_building() {
119 assert(_inc_build_state == Active, "Precondition");
120 assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
121
122 // The two "main" fields, _inc_recorded_rs_lengths and
123 // _inc_predicted_elapsed_time_ms, are updated by the thread
124 // that adds a new region to the CSet. Further updates by the
125 // concurrent refinement thread that samples the young RSet lengths
126 // are accumulated in the *_diffs fields. Here we add the diffs to
127 // the "main" fields.
128
129 if (_inc_recorded_rs_lengths_diffs >= 0) {
192 // information in the heap region here (before the region gets added
193 // to the collection set). An individual heap region's cached values
194 // are calculated, aggregated with the policy collection set info,
195 // and cached in the heap region here (initially) and (subsequently)
196 // by the Young List sampling code.
197
198 size_t rs_length = hr->rem_set()->occupied();
199 double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr);
200
201 // Cache the values we have added to the aggregated information
202 // in the heap region in case we have to remove this region from
203 // the incremental collection set, or it is updated by the
204 // rset sampling code
205 hr->set_recorded_rs_length(rs_length);
206 hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
207
208 size_t used_bytes = hr->used();
209 _inc_recorded_rs_lengths += rs_length;
210 _inc_predicted_elapsed_time_ms += region_elapsed_time_ms;
211 _inc_bytes_used_before += used_bytes;
212
213 assert(!hr->in_collection_set(), "invariant");
214 _g1->register_young_region_with_cset(hr);
215 assert(hr->next_in_collection_set() == NULL, "invariant");
216 }
217
218 // Add the region at the RHS of the incremental cset
219 void G1CollectionSet::add_survivor_regions(HeapRegion* hr) {
220 // We should only ever be appending survivors at the end of a pause
221 assert(hr->is_survivor(), "Logic");
222
223 // Do the 'common' stuff
224 add_young_region_common(hr);
225
226 // Now add the region at the right hand side
227 if (_inc_tail == NULL) {
228 assert(_inc_head == NULL, "invariant");
229 _inc_head = hr;
230 } else {
231 _inc_tail->set_next_in_collection_set(hr);
294 uint survivor_region_length = young_list->survivor_length();
295 uint eden_region_length = young_list->eden_length();
296 init_region_lengths(eden_region_length, survivor_region_length);
297
298 HeapRegion* hr = young_list->first_survivor_region();
299 while (hr != NULL) {
300 assert(hr->is_survivor(), "badly formed young list");
301 // There is a convention that all the young regions in the CSet
302 // are tagged as "eden", so we do this for the survivors here. We
303 // use the special set_eden_pre_gc() as it doesn't check that the
304 // region is free (which is not the case here).
305 hr->set_eden_pre_gc();
306 hr = hr->get_next_young_region();
307 }
308
309 // Clear the fields that point to the survivor list - they are all young now.
310 young_list->clear_survivors();
311
312 _head = _inc_head;
313 _bytes_used_before = _inc_bytes_used_before;
314 time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
315
316 log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
317 eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms);
318
319 // The number of recorded young regions is the incremental
320 // collection set's current size
321 set_recorded_rs_lengths(_inc_recorded_rs_lengths);
322
323 double young_end_time_sec = os::elapsedTime();
324 phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
325
326 return time_remaining_ms;
327 }
328
329 void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
330 double non_young_start_time_sec = os::elapsedTime();
331 double predicted_old_time_ms = 0.0;
332
333 if (!collector_state()->gcs_are_young()) {
334 cset_chooser()->verify();
335 const uint min_old_cset_length = _policy->calc_min_old_cset_length();
336 const uint max_old_cset_length = _policy->calc_max_old_cset_length();
337
338 uint expensive_region_num = 0;
339 bool check_time_remaining = _policy->adaptive_young_list_length();
340
341 HeapRegion* hr = cset_chooser()->peek();
342 while (hr != NULL) {
343 if (old_region_length() >= max_old_cset_length) {
344 // Added maximum number of old regions to the CSet.
345 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). old %u regions, max %u regions",
346 old_region_length(), max_old_cset_length);
347 break;
348 }
349
350 // Stop adding regions if the remaining reclaimable space is
351 // not above G1HeapWastePercent.
352 size_t reclaimable_bytes = cset_chooser()->remaining_reclaimable_bytes();
353 double reclaimable_perc = _policy->reclaimable_bytes_perc(reclaimable_bytes);
354 double threshold = (double) G1HeapWastePercent;
355 if (reclaimable_perc <= threshold) {
356 // We've added enough old regions that the amount of uncollected
357 // reclaimable space is at or below the waste threshold. Stop
358 // adding old regions to the CSet.
359 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
360 "old %u regions, max %u regions, reclaimable: " SIZE_FORMAT "B (%1.2f%%) threshold: " UINTX_FORMAT "%%",
361 old_region_length(), max_old_cset_length, reclaimable_bytes, reclaimable_perc, G1HeapWastePercent);
362 break;
363 }
364
365 double predicted_time_ms = predict_region_elapsed_time_ms(hr);
366 if (check_time_remaining) {
367 if (predicted_time_ms > time_remaining_ms) {
368 // Too expensive for the current CSet.
369
370 if (old_region_length() >= min_old_cset_length) {
371 // We have added the minimum number of old regions to the CSet,
372 // we are done with this CSet.
373 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high). "
374 "predicted time: %1.2fms, remaining time: %1.2fms old %u regions, min %u regions",
375 predicted_time_ms, time_remaining_ms, old_region_length(), min_old_cset_length);
376 break;
377 }
378
379 // We'll add it anyway given that we haven't reached the
380 // minimum number of old regions.
381 expensive_region_num += 1;
|