59 _collection_set_regions(NULL), |
59 _collection_set_regions(NULL), |
60 _collection_set_cur_length(0), |
60 _collection_set_cur_length(0), |
61 _collection_set_max_length(0), |
61 _collection_set_max_length(0), |
62 _num_optional_regions(0), |
62 _num_optional_regions(0), |
63 _bytes_used_before(0), |
63 _bytes_used_before(0), |
64 _recorded_rs_lengths(0), |
64 _recorded_rs_length(0), |
65 _inc_build_state(Inactive), |
65 _inc_build_state(Inactive), |
66 _inc_part_start(0), |
66 _inc_part_start(0), |
67 _inc_bytes_used_before(0), |
67 _inc_bytes_used_before(0), |
68 _inc_recorded_rs_lengths(0), |
68 _inc_recorded_rs_length(0), |
69 _inc_recorded_rs_lengths_diffs(0), |
69 _inc_recorded_rs_length_diff(0), |
70 _inc_predicted_elapsed_time_ms(0.0), |
70 _inc_predicted_elapsed_time_ms(0.0), |
71 _inc_predicted_elapsed_time_ms_diffs(0.0) { |
71 _inc_predicted_elapsed_time_ms_diff(0.0) { |
72 } |
72 } |
73 |
73 |
74 G1CollectionSet::~G1CollectionSet() { |
74 G1CollectionSet::~G1CollectionSet() { |
75 if (_collection_set_regions != NULL) { |
75 if (_collection_set_regions != NULL) { |
76 FREE_C_HEAP_ARRAY(uint, _collection_set_regions); |
76 FREE_C_HEAP_ARRAY(uint, _collection_set_regions); |
146 assert(_collection_set_cur_length == 0, "Collection set must be empty before starting a new collection set."); |
146 assert(_collection_set_cur_length == 0, "Collection set must be empty before starting a new collection set."); |
147 assert(_inc_build_state == Inactive, "Precondition"); |
147 assert(_inc_build_state == Inactive, "Precondition"); |
148 |
148 |
149 _inc_bytes_used_before = 0; |
149 _inc_bytes_used_before = 0; |
150 |
150 |
151 _inc_recorded_rs_lengths = 0; |
151 _inc_recorded_rs_length = 0; |
152 _inc_recorded_rs_lengths_diffs = 0; |
152 _inc_recorded_rs_length_diff = 0; |
153 _inc_predicted_elapsed_time_ms = 0.0; |
153 _inc_predicted_elapsed_time_ms = 0.0; |
154 _inc_predicted_elapsed_time_ms_diffs = 0.0; |
154 _inc_predicted_elapsed_time_ms_diff = 0.0; |
155 |
155 |
156 update_incremental_marker(); |
156 update_incremental_marker(); |
157 } |
157 } |
158 |
158 |
159 void G1CollectionSet::finalize_incremental_building() { |
159 void G1CollectionSet::finalize_incremental_building() { |
160 assert(_inc_build_state == Active, "Precondition"); |
160 assert(_inc_build_state == Active, "Precondition"); |
161 assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint"); |
161 assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint"); |
162 |
162 |
163 // The two "main" fields, _inc_recorded_rs_lengths and |
163 // The two "main" fields, _inc_recorded_rs_length and |
164 // _inc_predicted_elapsed_time_ms, are updated by the thread |
164 // _inc_predicted_elapsed_time_ms, are updated by the thread |
165 // that adds a new region to the CSet. Further updates by the |
165 // that adds a new region to the CSet. Further updates by the |
166 // concurrent refinement thread that samples the young RSet lengths |
166 // concurrent refinement thread that samples the young RSet lengths |
167 // are accumulated in the *_diffs fields. Here we add the diffs to |
167 // are accumulated in the *_diff fields. Here we add the diffs to |
168 // the "main" fields. |
168 // the "main" fields. |
169 |
169 |
170 if (_inc_recorded_rs_lengths_diffs >= 0) { |
170 if (_inc_recorded_rs_length_diff >= 0) { |
171 _inc_recorded_rs_lengths += _inc_recorded_rs_lengths_diffs; |
171 _inc_recorded_rs_length += _inc_recorded_rs_length_diff; |
172 } else { |
172 } else { |
173 // This is defensive. The diff should in theory be always positive |
173 // This is defensive. The diff should in theory be always positive |
174 // as RSets can only grow between GCs. However, given that we |
174 // as RSets can only grow between GCs. However, given that we |
175 // sample their size concurrently with other threads updating them |
175 // sample their size concurrently with other threads updating them |
176 // it's possible that we might get the wrong size back, which |
176 // it's possible that we might get the wrong size back, which |
177 // could make the calculations somewhat inaccurate. |
177 // could make the calculations somewhat inaccurate. |
178 size_t diffs = (size_t) (-_inc_recorded_rs_lengths_diffs); |
178 size_t diffs = (size_t) (-_inc_recorded_rs_length_diff); |
179 if (_inc_recorded_rs_lengths >= diffs) { |
179 if (_inc_recorded_rs_length >= diffs) { |
180 _inc_recorded_rs_lengths -= diffs; |
180 _inc_recorded_rs_length -= diffs; |
181 } else { |
181 } else { |
182 _inc_recorded_rs_lengths = 0; |
182 _inc_recorded_rs_length = 0; |
183 } |
183 } |
184 } |
184 } |
185 _inc_predicted_elapsed_time_ms += _inc_predicted_elapsed_time_ms_diffs; |
185 _inc_predicted_elapsed_time_ms += _inc_predicted_elapsed_time_ms_diff; |
186 |
186 |
187 _inc_recorded_rs_lengths_diffs = 0; |
187 _inc_recorded_rs_length_diff = 0; |
188 _inc_predicted_elapsed_time_ms_diffs = 0.0; |
188 _inc_predicted_elapsed_time_ms_diff = 0.0; |
189 } |
189 } |
190 |
190 |
191 void G1CollectionSet::clear() { |
191 void G1CollectionSet::clear() { |
192 assert_at_safepoint_on_vm_thread(); |
192 assert_at_safepoint_on_vm_thread(); |
193 _collection_set_cur_length = 0; |
193 _collection_set_cur_length = 0; |
250 size_t new_rs_length) { |
250 size_t new_rs_length) { |
251 // Update the CSet information that is dependent on the new RS length |
251 // Update the CSet information that is dependent on the new RS length |
252 assert(hr->is_young(), "Precondition"); |
252 assert(hr->is_young(), "Precondition"); |
253 assert(!SafepointSynchronize::is_at_safepoint(), "should not be at a safepoint"); |
253 assert(!SafepointSynchronize::is_at_safepoint(), "should not be at a safepoint"); |
254 |
254 |
255 // We could have updated _inc_recorded_rs_lengths and |
255 // We could have updated _inc_recorded_rs_length and |
256 // _inc_predicted_elapsed_time_ms directly but we'd need to do |
256 // _inc_predicted_elapsed_time_ms directly but we'd need to do |
257 // that atomically, as this code is executed by a concurrent |
257 // that atomically, as this code is executed by a concurrent |
258 // refinement thread, potentially concurrently with a mutator thread |
258 // refinement thread, potentially concurrently with a mutator thread |
259 // allocating a new region and also updating the same fields. To |
259 // allocating a new region and also updating the same fields. To |
260 // avoid the atomic operations we accumulate these updates on two |
260 // avoid the atomic operations we accumulate these updates on two |
261 // separate fields (*_diffs) and we'll just add them to the "main" |
261 // separate fields (*_diff) and we'll just add them to the "main" |
262 // fields at the start of a GC. |
262 // fields at the start of a GC. |
263 |
263 |
264 ssize_t old_rs_length = (ssize_t) hr->recorded_rs_length(); |
264 ssize_t old_rs_length = (ssize_t) hr->recorded_rs_length(); |
265 ssize_t rs_lengths_diff = (ssize_t) new_rs_length - old_rs_length; |
265 ssize_t rs_length_diff = (ssize_t) new_rs_length - old_rs_length; |
266 _inc_recorded_rs_lengths_diffs += rs_lengths_diff; |
266 _inc_recorded_rs_length_diff += rs_length_diff; |
267 |
267 |
268 double old_elapsed_time_ms = hr->predicted_elapsed_time_ms(); |
268 double old_elapsed_time_ms = hr->predicted_elapsed_time_ms(); |
269 double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr); |
269 double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr); |
270 double elapsed_ms_diff = new_region_elapsed_time_ms - old_elapsed_time_ms; |
270 double elapsed_ms_diff = new_region_elapsed_time_ms - old_elapsed_time_ms; |
271 _inc_predicted_elapsed_time_ms_diffs += elapsed_ms_diff; |
271 _inc_predicted_elapsed_time_ms_diff += elapsed_ms_diff; |
272 |
272 |
273 hr->set_recorded_rs_length(new_rs_length); |
273 hr->set_recorded_rs_length(new_rs_length); |
274 hr->set_predicted_elapsed_time_ms(new_region_elapsed_time_ms); |
274 hr->set_predicted_elapsed_time_ms(new_region_elapsed_time_ms); |
275 } |
275 } |
276 |
276 |
314 // the incremental collection set, or it is updated by the |
314 // the incremental collection set, or it is updated by the |
315 // rset sampling code |
315 // rset sampling code |
316 hr->set_recorded_rs_length(rs_length); |
316 hr->set_recorded_rs_length(rs_length); |
317 hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms); |
317 hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms); |
318 |
318 |
319 _inc_recorded_rs_lengths += rs_length; |
319 _inc_recorded_rs_length += rs_length; |
320 _inc_predicted_elapsed_time_ms += region_elapsed_time_ms; |
320 _inc_predicted_elapsed_time_ms += region_elapsed_time_ms; |
321 _inc_bytes_used_before += hr->used(); |
321 _inc_bytes_used_before += hr->used(); |
322 } |
322 } |
323 |
323 |
324 assert(!hr->in_collection_set(), "invariant"); |
324 assert(!hr->in_collection_set(), "invariant"); |
435 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", |
435 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", |
436 eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms); |
436 eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms); |
437 |
437 |
438 // The number of recorded young regions is the incremental |
438 // The number of recorded young regions is the incremental |
439 // collection set's current size |
439 // collection set's current size |
440 set_recorded_rs_lengths(_inc_recorded_rs_lengths); |
440 set_recorded_rs_length(_inc_recorded_rs_length); |
441 |
441 |
442 double young_end_time_sec = os::elapsedTime(); |
442 double young_end_time_sec = os::elapsedTime(); |
443 phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0); |
443 phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0); |
444 |
444 |
445 return time_remaining_ms; |
445 return time_remaining_ms; |