1 /*
2 * Copyright (c) 2001, 2019, 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 *
173 // Range check assertions for green, yellow, and red zone values.
174 #define assert_zone_constraints_gyr(green, yellow, red) \
175 do { \
176 size_t azc_gyr_green = (green); \
177 size_t azc_gyr_yellow = (yellow); \
178 size_t azc_gyr_red = (red); \
179 assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \
180 assert(azc_gyr_red <= max_red_zone, \
181 "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \
182 assert(azc_gyr_yellow <= azc_gyr_red, \
183 "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \
184 azc_gyr_yellow, azc_gyr_red); \
185 } while (0)
186
187 // Logging tag sequence for refinement control updates.
188 #define CTRL_TAGS gc, ergo, refine
189
190 // For logging zone values, ensuring consistency of level and tags.
191 #define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__)
192
193 // Package for pair of refinement thread activation and deactivation
194 // thresholds. The activation and deactivation levels are resp. the first
195 // and second values of the pair.
196 typedef Pair<size_t, size_t> Thresholds;
197 inline size_t activation_level(const Thresholds& t) { return t.first; }
198 inline size_t deactivation_level(const Thresholds& t) { return t.second; }
199
200 static Thresholds calc_thresholds(size_t green_zone,
201 size_t yellow_zone,
202 uint worker_id) {
203 double yellow_size = yellow_zone - green_zone;
204 double step = yellow_size / G1ConcurrentRefine::max_num_threads();
205 if (worker_id == 0) {
206 // Potentially activate worker 0 more aggressively, to keep
207 // available buffers near green_zone value. When yellow_size is
208 // large we don't want to allow a full step to accumulate before
209 // doing any processing, as that might lead to significantly more
210 // than green_zone buffers to be processed during scanning.
211 step = MIN2(step, ParallelGCThreads / 2.0);
212 }
213 size_t activate_offset = static_cast<size_t>(ceil(step * (worker_id + 1)));
214 size_t deactivate_offset = static_cast<size_t>(floor(step * worker_id));
215 return Thresholds(green_zone + activate_offset,
216 green_zone + deactivate_offset);
217 }
218
219 G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone,
220 size_t yellow_zone,
221 size_t red_zone,
222 size_t min_yellow_zone_size) :
223 _thread_control(),
224 _green_zone(green_zone),
225 _yellow_zone(yellow_zone),
226 _red_zone(red_zone),
227 _min_yellow_zone_size(min_yellow_zone_size)
228 {
229 assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
230 }
231
232 jint G1ConcurrentRefine::initialize() {
233 return _thread_control.initialize(this, max_num_threads());
234 }
235
236 static size_t buffers_to_cards(size_t value) {
237 return value * G1UpdateBufferSize;
238 }
239
240 static size_t calc_min_yellow_zone_size() {
241 size_t step = buffers_to_cards(G1ConcRefinementThresholdStep);
242 uint n_workers = G1ConcurrentRefine::max_num_threads();
243 if ((max_yellow_zone / step) < n_workers) {
244 return max_yellow_zone;
245 } else {
246 return step * n_workers;
247 }
248 }
249
250 static size_t calc_init_green_zone() {
251 size_t green = G1ConcRefinementGreenZone;
252 if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
253 green = ParallelGCThreads;
254 }
255 green = buffers_to_cards(green);
256 return MIN2(green, max_green_zone);
257 }
258
259 static size_t calc_init_yellow_zone(size_t green, size_t min_size) {
426 } collector;
427 // Cast away const so we can call non-modifying closure on threads.
428 const_cast<G1ConcurrentRefine*>(this)->threads_do(&collector);
429 return RefinementStats(collector._total_time, collector._total_cards);
430 }
431
432 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
433 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
434 return activation_level(thresholds);
435 }
436
437 size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
438 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
439 return deactivation_level(thresholds);
440 }
441
442 uint G1ConcurrentRefine::worker_id_offset() {
443 return G1DirtyCardQueueSet::num_par_ids();
444 }
445
446 void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) {
447 if (num_cur_buffers > activation_threshold(worker_id + 1)) {
448 _thread_control.maybe_activate_next(worker_id);
449 }
450 }
451
452 bool G1ConcurrentRefine::do_refinement_step(uint worker_id,
453 size_t* total_refined_cards) {
454 G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
455
456 size_t curr_cards = dcqs.num_cards();
457 // If the number of the cards falls down into the yellow zone,
458 // that means that the transition period after the evacuation pause has ended.
459 // Since the value written to the DCQS is the same for all threads, there is no
460 // need to synchronize.
461 if (dcqs.max_cards_padding() > 0 && curr_cards <= yellow_zone()) {
462 dcqs.set_max_cards_padding(0);
463 }
464
465 maybe_activate_more_threads(worker_id, curr_cards);
466
467 // Process the next buffer, if there are enough left.
|
1 /*
2 * Copyright (c) 2001, 2020, 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 *
173 // Range check assertions for green, yellow, and red zone values.
174 #define assert_zone_constraints_gyr(green, yellow, red) \
175 do { \
176 size_t azc_gyr_green = (green); \
177 size_t azc_gyr_yellow = (yellow); \
178 size_t azc_gyr_red = (red); \
179 assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \
180 assert(azc_gyr_red <= max_red_zone, \
181 "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \
182 assert(azc_gyr_yellow <= azc_gyr_red, \
183 "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \
184 azc_gyr_yellow, azc_gyr_red); \
185 } while (0)
186
187 // Logging tag sequence for refinement control updates.
188 #define CTRL_TAGS gc, ergo, refine
189
190 // For logging zone values, ensuring consistency of level and tags.
191 #define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__)
192
193 static size_t buffers_to_cards(size_t value) {
194 return value * G1UpdateBufferSize;
195 }
196
197 // Package for pair of refinement thread activation and deactivation
198 // thresholds. The activation and deactivation levels are resp. the first
199 // and second values of the pair.
200 typedef Pair<size_t, size_t> Thresholds;
201 inline size_t activation_level(const Thresholds& t) { return t.first; }
202 inline size_t deactivation_level(const Thresholds& t) { return t.second; }
203
204 static Thresholds calc_thresholds(size_t green_zone,
205 size_t yellow_zone,
206 uint worker_id) {
207 double yellow_size = yellow_zone - green_zone;
208 double step = yellow_size / G1ConcurrentRefine::max_num_threads();
209 if (worker_id == 0) {
210 // Potentially activate worker 0 more aggressively, to keep
211 // available buffers near green_zone value. When yellow_size is
212 // large we don't want to allow a full step to accumulate before
213 // doing any processing, as that might lead to significantly more
214 // than green_zone buffers to be processed during pause. So limit
215 // to an extra half buffer per pause-time processing thread.
216 step = MIN2(step, buffers_to_cards(ParallelGCThreads) / 2.0);
217 }
218 size_t activate_offset = static_cast<size_t>(ceil(step * (worker_id + 1)));
219 size_t deactivate_offset = static_cast<size_t>(floor(step * worker_id));
220 return Thresholds(green_zone + activate_offset,
221 green_zone + deactivate_offset);
222 }
223
224 G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone,
225 size_t yellow_zone,
226 size_t red_zone,
227 size_t min_yellow_zone_size) :
228 _thread_control(),
229 _green_zone(green_zone),
230 _yellow_zone(yellow_zone),
231 _red_zone(red_zone),
232 _min_yellow_zone_size(min_yellow_zone_size)
233 {
234 assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
235 }
236
237 jint G1ConcurrentRefine::initialize() {
238 return _thread_control.initialize(this, max_num_threads());
239 }
240
241 static size_t calc_min_yellow_zone_size() {
242 size_t step = buffers_to_cards(G1ConcRefinementThresholdStep);
243 uint n_workers = G1ConcurrentRefine::max_num_threads();
244 if ((max_yellow_zone / step) < n_workers) {
245 return max_yellow_zone;
246 } else {
247 return step * n_workers;
248 }
249 }
250
251 static size_t calc_init_green_zone() {
252 size_t green = G1ConcRefinementGreenZone;
253 if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
254 green = ParallelGCThreads;
255 }
256 green = buffers_to_cards(green);
257 return MIN2(green, max_green_zone);
258 }
259
260 static size_t calc_init_yellow_zone(size_t green, size_t min_size) {
427 } collector;
428 // Cast away const so we can call non-modifying closure on threads.
429 const_cast<G1ConcurrentRefine*>(this)->threads_do(&collector);
430 return RefinementStats(collector._total_time, collector._total_cards);
431 }
432
433 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
434 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
435 return activation_level(thresholds);
436 }
437
438 size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
439 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
440 return deactivation_level(thresholds);
441 }
442
443 uint G1ConcurrentRefine::worker_id_offset() {
444 return G1DirtyCardQueueSet::num_par_ids();
445 }
446
447 void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_cards) {
448 if (num_cur_cards > activation_threshold(worker_id + 1)) {
449 _thread_control.maybe_activate_next(worker_id);
450 }
451 }
452
453 bool G1ConcurrentRefine::do_refinement_step(uint worker_id,
454 size_t* total_refined_cards) {
455 G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
456
457 size_t curr_cards = dcqs.num_cards();
458 // If the number of the cards falls down into the yellow zone,
459 // that means that the transition period after the evacuation pause has ended.
460 // Since the value written to the DCQS is the same for all threads, there is no
461 // need to synchronize.
462 if (dcqs.max_cards_padding() > 0 && curr_cards <= yellow_zone()) {
463 dcqs.set_max_cards_padding(0);
464 }
465
466 maybe_activate_more_threads(worker_id, curr_cards);
467
468 // Process the next buffer, if there are enough left.
|