< prev index next >

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

Print this page
rev 56066 : [mq]: card_units
rev 56067 : [mq]: renaming


 128     }
 129   }
 130 }
 131 
 132 void G1ConcurrentRefineThreadControl::stop() {
 133   for (uint i = 0; i < _num_max_threads; i++) {
 134     if (_threads[i] != NULL) {
 135       _threads[i]->stop();
 136     }
 137   }
 138 }
 139 
 140 // Arbitrary but large limits, to simplify some of the zone calculations.
 141 // The general idea is to allow expressions like
 142 //   MIN2(x OP y, max_XXX_zone)
 143 // without needing to check for overflow in "x OP y", because the
 144 // ranges for x and y have been restricted.
 145 STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2));
 146 const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort);
 147 const size_t max_green_zone = max_yellow_zone / 2;
 148 const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_buffers.
 149 STATIC_ASSERT(max_yellow_zone <= max_red_zone);
 150 
 151 // Range check assertions for green zone values.
 152 #define assert_zone_constraints_g(green)                        \
 153   do {                                                          \
 154     size_t azc_g_green = (green);                               \
 155     assert(azc_g_green <= max_green_zone,                       \
 156            "green exceeds max: " SIZE_FORMAT, azc_g_green);     \
 157   } while (0)
 158 
 159 // Range check assertions for green and yellow zone values.
 160 #define assert_zone_constraints_gy(green, yellow)                       \
 161   do {                                                                  \
 162     size_t azc_gy_green = (green);                                      \
 163     size_t azc_gy_yellow = (yellow);                                    \
 164     assert_zone_constraints_g(azc_gy_green);                            \
 165     assert(azc_gy_yellow <= max_yellow_zone,                            \
 166            "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow);          \
 167     assert(azc_gy_green <= azc_gy_yellow,                               \
 168            "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")",  \


 215                     green_zone + deactivate_offset);
 216 }
 217 
 218 G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone,
 219                                        size_t yellow_zone,
 220                                        size_t red_zone,
 221                                        size_t min_yellow_zone_size) :
 222   _thread_control(),
 223   _green_zone(green_zone),
 224   _yellow_zone(yellow_zone),
 225   _red_zone(red_zone),
 226   _min_yellow_zone_size(min_yellow_zone_size)
 227 {
 228   assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
 229 }
 230 
 231 jint G1ConcurrentRefine::initialize() {
 232   return _thread_control.initialize(this, max_num_threads());
 233 }
 234 




 235 static size_t calc_min_yellow_zone_size() {
 236   size_t step = G1ConcRefinementThresholdStep;
 237   uint n_workers = G1ConcurrentRefine::max_num_threads();
 238   if ((max_yellow_zone / step) < n_workers) {
 239     return max_yellow_zone;
 240   } else {
 241     return step * n_workers;
 242   }
 243 }
 244 
 245 static size_t calc_init_green_zone() {
 246   size_t green = G1ConcRefinementGreenZone;
 247   if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
 248     green = ParallelGCThreads;
 249   }

 250   return MIN2(green, max_green_zone);
 251 }
 252 
 253 static size_t calc_init_yellow_zone(size_t green, size_t min_size) {
 254   size_t config = G1ConcRefinementYellowZone;
 255   size_t size = 0;
 256   if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) {
 257     size = green * 2;
 258   } else if (green < config) {
 259     size = config - green;
 260   }
 261   size = MAX2(size, min_size);
 262   size = MIN2(size, max_yellow_zone);
 263   return MIN2(green + size, max_yellow_zone);
 264 }
 265 
 266 static size_t calc_init_red_zone(size_t green, size_t yellow) {
 267   size_t size = yellow - green;
 268   if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) {
 269     size_t config = G1ConcRefinementRedZone;
 270     if (yellow < config) {
 271       size = MAX2(size, config - yellow);
 272     }
 273   }
 274   return MIN2(yellow + size, max_red_zone);
 275 }
 276 
 277 G1ConcurrentRefine* G1ConcurrentRefine::create(jint* ecode) {
 278   size_t min_yellow_zone_size = calc_min_yellow_zone_size();
 279   size_t green_zone = calc_init_green_zone();
 280   size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size);
 281   size_t red_zone = calc_init_red_zone(green_zone, yellow_zone);
 282 
 283   LOG_ZONES("Initial Refinement Zones: "
 284             "green: " SIZE_FORMAT ", "
 285             "yellow: " SIZE_FORMAT ", "
 286             "red: " SIZE_FORMAT ", "
 287             "min yellow size: " SIZE_FORMAT,
 288             green_zone, yellow_zone, red_zone, min_yellow_zone_size);
 289 


 305 void G1ConcurrentRefine::stop() {
 306   _thread_control.stop();
 307 }
 308 
 309 G1ConcurrentRefine::~G1ConcurrentRefine() {
 310 }
 311 
 312 void G1ConcurrentRefine::threads_do(ThreadClosure *tc) {
 313   _thread_control.worker_threads_do(tc);
 314 }
 315 
 316 uint G1ConcurrentRefine::max_num_threads() {
 317   return G1ConcRefinementThreads;
 318 }
 319 
 320 void G1ConcurrentRefine::print_threads_on(outputStream* st) const {
 321   _thread_control.print_on(st);
 322 }
 323 
 324 static size_t calc_new_green_zone(size_t green,
 325                                   double log_buffer_scan_time,
 326                                   size_t processed_log_buffers,
 327                                   double goal_ms) {
 328   // Adjust green zone based on whether we're meeting the time goal.
 329   // Limit to max_green_zone.
 330   const double inc_k = 1.1, dec_k = 0.9;
 331   if (log_buffer_scan_time > goal_ms) {
 332     if (green > 0) {
 333       green = static_cast<size_t>(green * dec_k);
 334     }
 335   } else if (log_buffer_scan_time < goal_ms &&
 336              processed_log_buffers > green) {
 337     green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0));
 338     green = MIN2(green, max_green_zone);
 339   }
 340   return green;
 341 }
 342 
 343 static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) {
 344   size_t size = green * 2;
 345   size = MAX2(size, min_yellow_size);
 346   return MIN2(green + size, max_yellow_zone);
 347 }
 348 
 349 static size_t calc_new_red_zone(size_t green, size_t yellow) {
 350   return MIN2(yellow + (yellow - green), max_red_zone);
 351 }
 352 
 353 void G1ConcurrentRefine::update_zones(double log_buffer_scan_time,
 354                                       size_t processed_log_buffers,
 355                                       double goal_ms) {
 356   log_trace( CTRL_TAGS )("Updating Refinement Zones: "
 357                          "log buffer scan time: %.3fms, "
 358                          "processed buffers: " SIZE_FORMAT ", "
 359                          "goal time: %.3fms",
 360                          log_buffer_scan_time,
 361                          processed_log_buffers,
 362                          goal_ms);
 363 
 364   _green_zone = calc_new_green_zone(_green_zone,
 365                                     log_buffer_scan_time,
 366                                     processed_log_buffers,
 367                                     goal_ms);
 368   _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size);
 369   _red_zone = calc_new_red_zone(_green_zone, _yellow_zone);
 370 
 371   assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone);
 372   LOG_ZONES("Updated Refinement Zones: "
 373             "green: " SIZE_FORMAT ", "
 374             "yellow: " SIZE_FORMAT ", "
 375             "red: " SIZE_FORMAT,
 376             _green_zone, _yellow_zone, _red_zone);
 377 }
 378 
 379 void G1ConcurrentRefine::adjust(double log_buffer_scan_time,
 380                                 size_t processed_log_buffers,
 381                                 double goal_ms) {
 382   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 383 
 384   if (G1UseAdaptiveConcRefinement) {
 385     update_zones(log_buffer_scan_time, processed_log_buffers, goal_ms);
 386 
 387     // Change the barrier params
 388     if (max_num_threads() == 0) {
 389       // Disable dcqs notification when there are no threads to notify.
 390       dcqs.set_process_completed_buffers_threshold(G1DirtyCardQueueSet::ProcessCompletedBuffersThresholdNever);
 391     } else {
 392       // Worker 0 is the primary; wakeup is via dcqs notification.
 393       STATIC_ASSERT(max_yellow_zone <= INT_MAX);
 394       size_t activate = activation_threshold(0);
 395       dcqs.set_process_completed_buffers_threshold(activate);
 396     }
 397     dcqs.set_max_completed_buffers(red_zone());
 398   }
 399 
 400   size_t curr_queue_size = dcqs.num_completed_buffers();
 401   if ((dcqs.max_completed_buffers() > 0) &&
 402       (curr_queue_size >= yellow_zone())) {
 403     dcqs.set_completed_buffers_padding(curr_queue_size);
 404   } else {
 405     dcqs.set_completed_buffers_padding(0);
 406   }
 407   dcqs.notify_if_necessary();
 408 }
 409 
 410 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
 411   Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
 412   return activation_level(thresholds);
 413 }
 414 
 415 size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
 416   Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
 417   return deactivation_level(thresholds);
 418 }
 419 
 420 uint G1ConcurrentRefine::worker_id_offset() {
 421   return G1DirtyCardQueueSet::num_par_ids();
 422 }
 423 
 424 void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) {
 425   if (num_cur_buffers > activation_threshold(worker_id + 1)) {
 426     _thread_control.maybe_activate_next(worker_id);
 427   }
 428 }
 429 
 430 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
 431   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 432 
 433   size_t curr_buffer_num = dcqs.num_completed_buffers();
 434   // If the number of the buffers falls down into the yellow zone,
 435   // that means that the transition period after the evacuation pause has ended.
 436   // Since the value written to the DCQS is the same for all threads, there is no
 437   // need to synchronize.
 438   if (dcqs.completed_buffers_padding() > 0 && curr_buffer_num <= yellow_zone()) {
 439     dcqs.set_completed_buffers_padding(0);
 440   }
 441 
 442   maybe_activate_more_threads(worker_id, curr_buffer_num);
 443 
 444   // Process the next buffer, if there are enough left.
 445   return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(),
 446                                                    deactivation_threshold(worker_id));
 447 }


 128     }
 129   }
 130 }
 131 
 132 void G1ConcurrentRefineThreadControl::stop() {
 133   for (uint i = 0; i < _num_max_threads; i++) {
 134     if (_threads[i] != NULL) {
 135       _threads[i]->stop();
 136     }
 137   }
 138 }
 139 
 140 // Arbitrary but large limits, to simplify some of the zone calculations.
 141 // The general idea is to allow expressions like
 142 //   MIN2(x OP y, max_XXX_zone)
 143 // without needing to check for overflow in "x OP y", because the
 144 // ranges for x and y have been restricted.
 145 STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2));
 146 const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort);
 147 const size_t max_green_zone = max_yellow_zone / 2;
 148 const size_t max_red_zone = INT_MAX; // For dcqs.set_max_cards.
 149 STATIC_ASSERT(max_yellow_zone <= max_red_zone);
 150 
 151 // Range check assertions for green zone values.
 152 #define assert_zone_constraints_g(green)                        \
 153   do {                                                          \
 154     size_t azc_g_green = (green);                               \
 155     assert(azc_g_green <= max_green_zone,                       \
 156            "green exceeds max: " SIZE_FORMAT, azc_g_green);     \
 157   } while (0)
 158 
 159 // Range check assertions for green and yellow zone values.
 160 #define assert_zone_constraints_gy(green, yellow)                       \
 161   do {                                                                  \
 162     size_t azc_gy_green = (green);                                      \
 163     size_t azc_gy_yellow = (yellow);                                    \
 164     assert_zone_constraints_g(azc_gy_green);                            \
 165     assert(azc_gy_yellow <= max_yellow_zone,                            \
 166            "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow);          \
 167     assert(azc_gy_green <= azc_gy_yellow,                               \
 168            "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")",  \


 215                     green_zone + deactivate_offset);
 216 }
 217 
 218 G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone,
 219                                        size_t yellow_zone,
 220                                        size_t red_zone,
 221                                        size_t min_yellow_zone_size) :
 222   _thread_control(),
 223   _green_zone(green_zone),
 224   _yellow_zone(yellow_zone),
 225   _red_zone(red_zone),
 226   _min_yellow_zone_size(min_yellow_zone_size)
 227 {
 228   assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
 229 }
 230 
 231 jint G1ConcurrentRefine::initialize() {
 232   return _thread_control.initialize(this, max_num_threads());
 233 }
 234 
 235 static size_t buffers_to_cards(size_t value) {
 236   return value * G1UpdateBufferSize;
 237 }
 238 
 239 static size_t calc_min_yellow_zone_size() {
 240   size_t step = buffers_to_cards(G1ConcRefinementThresholdStep);
 241   uint n_workers = G1ConcurrentRefine::max_num_threads();
 242   if ((max_yellow_zone / step) < n_workers) {
 243     return max_yellow_zone;
 244   } else {
 245     return step * n_workers;
 246   }
 247 }
 248 
 249 static size_t calc_init_green_zone() {
 250   size_t green = G1ConcRefinementGreenZone;
 251   if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
 252     green = ParallelGCThreads;
 253   }
 254   green = buffers_to_cards(green);
 255   return MIN2(green, max_green_zone);
 256 }
 257 
 258 static size_t calc_init_yellow_zone(size_t green, size_t min_size) {
 259   size_t config = buffers_to_cards(G1ConcRefinementYellowZone);
 260   size_t size = 0;
 261   if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) {
 262     size = green * 2;
 263   } else if (green < config) {
 264     size = config - green;
 265   }
 266   size = MAX2(size, min_size);
 267   size = MIN2(size, max_yellow_zone);
 268   return MIN2(green + size, max_yellow_zone);
 269 }
 270 
 271 static size_t calc_init_red_zone(size_t green, size_t yellow) {
 272   size_t size = yellow - green;
 273   if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) {
 274     size_t config = buffers_to_cards(G1ConcRefinementRedZone);
 275     if (yellow < config) {
 276       size = MAX2(size, config - yellow);
 277     }
 278   }
 279   return MIN2(yellow + size, max_red_zone);
 280 }
 281 
 282 G1ConcurrentRefine* G1ConcurrentRefine::create(jint* ecode) {
 283   size_t min_yellow_zone_size = calc_min_yellow_zone_size();
 284   size_t green_zone = calc_init_green_zone();
 285   size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size);
 286   size_t red_zone = calc_init_red_zone(green_zone, yellow_zone);
 287 
 288   LOG_ZONES("Initial Refinement Zones: "
 289             "green: " SIZE_FORMAT ", "
 290             "yellow: " SIZE_FORMAT ", "
 291             "red: " SIZE_FORMAT ", "
 292             "min yellow size: " SIZE_FORMAT,
 293             green_zone, yellow_zone, red_zone, min_yellow_zone_size);
 294 


 310 void G1ConcurrentRefine::stop() {
 311   _thread_control.stop();
 312 }
 313 
 314 G1ConcurrentRefine::~G1ConcurrentRefine() {
 315 }
 316 
 317 void G1ConcurrentRefine::threads_do(ThreadClosure *tc) {
 318   _thread_control.worker_threads_do(tc);
 319 }
 320 
 321 uint G1ConcurrentRefine::max_num_threads() {
 322   return G1ConcRefinementThreads;
 323 }
 324 
 325 void G1ConcurrentRefine::print_threads_on(outputStream* st) const {
 326   _thread_control.print_on(st);
 327 }
 328 
 329 static size_t calc_new_green_zone(size_t green,
 330                                   double logged_cards_scan_time,
 331                                   size_t processed_logged_cards,
 332                                   double goal_ms) {
 333   // Adjust green zone based on whether we're meeting the time goal.
 334   // Limit to max_green_zone.
 335   const double inc_k = 1.1, dec_k = 0.9;
 336   if (logged_cards_scan_time > goal_ms) {
 337     if (green > 0) {
 338       green = static_cast<size_t>(green * dec_k);
 339     }
 340   } else if (logged_cards_scan_time < goal_ms &&
 341              processed_logged_cards > green) {
 342     green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0));
 343     green = MIN2(green, max_green_zone);
 344   }
 345   return green;
 346 }
 347 
 348 static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) {
 349   size_t size = green * 2;
 350   size = MAX2(size, min_yellow_size);
 351   return MIN2(green + size, max_yellow_zone);
 352 }
 353 
 354 static size_t calc_new_red_zone(size_t green, size_t yellow) {
 355   return MIN2(yellow + (yellow - green), max_red_zone);
 356 }
 357 
 358 void G1ConcurrentRefine::update_zones(double logged_cards_scan_time,
 359                                       size_t processed_logged_cards,
 360                                       double goal_ms) {
 361   log_trace( CTRL_TAGS )("Updating Refinement Zones: "
 362                          "logged cards scan time: %.3fms, "
 363                          "processed cards: " SIZE_FORMAT ", "
 364                          "goal time: %.3fms",
 365                          logged_cards_scan_time,
 366                          processed_logged_cards,
 367                          goal_ms);
 368 
 369   _green_zone = calc_new_green_zone(_green_zone,
 370                                     logged_cards_scan_time,
 371                                     processed_logged_cards,
 372                                     goal_ms);
 373   _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size);
 374   _red_zone = calc_new_red_zone(_green_zone, _yellow_zone);
 375 
 376   assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone);
 377   LOG_ZONES("Updated Refinement Zones: "
 378             "green: " SIZE_FORMAT ", "
 379             "yellow: " SIZE_FORMAT ", "
 380             "red: " SIZE_FORMAT,
 381             _green_zone, _yellow_zone, _red_zone);
 382 }
 383 
 384 void G1ConcurrentRefine::adjust(double logged_cards_scan_time,
 385                                 size_t processed_logged_cards,
 386                                 double goal_ms) {
 387   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 388 
 389   if (G1UseAdaptiveConcRefinement) {
 390     update_zones(logged_cards_scan_time, processed_logged_cards, goal_ms);
 391 
 392     // Change the barrier params
 393     if (max_num_threads() == 0) {
 394       // Disable dcqs notification when there are no threads to notify.
 395       dcqs.set_process_cards_threshold(G1DirtyCardQueueSet::ProcessCardsThresholdNever);
 396     } else {
 397       // Worker 0 is the primary; wakeup is via dcqs notification.
 398       STATIC_ASSERT(max_yellow_zone <= INT_MAX);
 399       size_t activate = activation_threshold(0);
 400       dcqs.set_process_cards_threshold(activate);
 401     }
 402     dcqs.set_max_cards(red_zone());
 403   }
 404 
 405   size_t curr_queue_size = dcqs.num_cards();
 406   if ((dcqs.max_cards() > 0) &&
 407       (curr_queue_size >= yellow_zone())) {
 408     dcqs.set_max_cards_padding(curr_queue_size);
 409   } else {
 410     dcqs.set_max_cards_padding(0);
 411   }
 412   dcqs.notify_if_necessary();
 413 }
 414 
 415 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
 416   Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
 417   return activation_level(thresholds);
 418 }
 419 
 420 size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
 421   Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
 422   return deactivation_level(thresholds);
 423 }
 424 
 425 uint G1ConcurrentRefine::worker_id_offset() {
 426   return G1DirtyCardQueueSet::num_par_ids();
 427 }
 428 
 429 void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) {
 430   if (num_cur_buffers > activation_threshold(worker_id + 1)) {
 431     _thread_control.maybe_activate_next(worker_id);
 432   }
 433 }
 434 
 435 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
 436   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 437 
 438   size_t curr_cards = dcqs.num_cards();
 439   // If the number of the cards falls down into the yellow zone,
 440   // that means that the transition period after the evacuation pause has ended.
 441   // Since the value written to the DCQS is the same for all threads, there is no
 442   // need to synchronize.
 443   if (dcqs.max_cards_padding() > 0 && curr_cards <= yellow_zone()) {
 444     dcqs.set_max_cards_padding(0);
 445   }
 446 
 447   maybe_activate_more_threads(worker_id, curr_cards);
 448 
 449   // Process the next buffer, if there are enough left.
 450   return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(),
 451                                                    deactivation_threshold(worker_id));
 452 }
< prev index next >