143 // without needing to check for overflow in "x OP y", because the |
143 // without needing to check for overflow in "x OP y", because the |
144 // ranges for x and y have been restricted. |
144 // ranges for x and y have been restricted. |
145 STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2)); |
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); |
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; |
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. |
148 const size_t max_red_zone = INT_MAX; // For dcqs.set_max_cards. |
149 STATIC_ASSERT(max_yellow_zone <= max_red_zone); |
149 STATIC_ASSERT(max_yellow_zone <= max_red_zone); |
150 |
150 |
151 // Range check assertions for green zone values. |
151 // Range check assertions for green zone values. |
152 #define assert_zone_constraints_g(green) \ |
152 #define assert_zone_constraints_g(green) \ |
153 do { \ |
153 do { \ |
230 |
230 |
231 jint G1ConcurrentRefine::initialize() { |
231 jint G1ConcurrentRefine::initialize() { |
232 return _thread_control.initialize(this, max_num_threads()); |
232 return _thread_control.initialize(this, max_num_threads()); |
233 } |
233 } |
234 |
234 |
|
235 static size_t buffers_to_cards(size_t value) { |
|
236 return value * G1UpdateBufferSize; |
|
237 } |
|
238 |
235 static size_t calc_min_yellow_zone_size() { |
239 static size_t calc_min_yellow_zone_size() { |
236 size_t step = G1ConcRefinementThresholdStep; |
240 size_t step = buffers_to_cards(G1ConcRefinementThresholdStep); |
237 uint n_workers = G1ConcurrentRefine::max_num_threads(); |
241 uint n_workers = G1ConcurrentRefine::max_num_threads(); |
238 if ((max_yellow_zone / step) < n_workers) { |
242 if ((max_yellow_zone / step) < n_workers) { |
239 return max_yellow_zone; |
243 return max_yellow_zone; |
240 } else { |
244 } else { |
241 return step * n_workers; |
245 return step * n_workers; |
245 static size_t calc_init_green_zone() { |
249 static size_t calc_init_green_zone() { |
246 size_t green = G1ConcRefinementGreenZone; |
250 size_t green = G1ConcRefinementGreenZone; |
247 if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { |
251 if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { |
248 green = ParallelGCThreads; |
252 green = ParallelGCThreads; |
249 } |
253 } |
|
254 green = buffers_to_cards(green); |
250 return MIN2(green, max_green_zone); |
255 return MIN2(green, max_green_zone); |
251 } |
256 } |
252 |
257 |
253 static size_t calc_init_yellow_zone(size_t green, size_t min_size) { |
258 static size_t calc_init_yellow_zone(size_t green, size_t min_size) { |
254 size_t config = G1ConcRefinementYellowZone; |
259 size_t config = buffers_to_cards(G1ConcRefinementYellowZone); |
255 size_t size = 0; |
260 size_t size = 0; |
256 if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { |
261 if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { |
257 size = green * 2; |
262 size = green * 2; |
258 } else if (green < config) { |
263 } else if (green < config) { |
259 size = config - green; |
264 size = config - green; |
264 } |
269 } |
265 |
270 |
266 static size_t calc_init_red_zone(size_t green, size_t yellow) { |
271 static size_t calc_init_red_zone(size_t green, size_t yellow) { |
267 size_t size = yellow - green; |
272 size_t size = yellow - green; |
268 if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { |
273 if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { |
269 size_t config = G1ConcRefinementRedZone; |
274 size_t config = buffers_to_cards(G1ConcRefinementRedZone); |
270 if (yellow < config) { |
275 if (yellow < config) { |
271 size = MAX2(size, config - yellow); |
276 size = MAX2(size, config - yellow); |
272 } |
277 } |
273 } |
278 } |
274 return MIN2(yellow + size, max_red_zone); |
279 return MIN2(yellow + size, max_red_zone); |
320 void G1ConcurrentRefine::print_threads_on(outputStream* st) const { |
325 void G1ConcurrentRefine::print_threads_on(outputStream* st) const { |
321 _thread_control.print_on(st); |
326 _thread_control.print_on(st); |
322 } |
327 } |
323 |
328 |
324 static size_t calc_new_green_zone(size_t green, |
329 static size_t calc_new_green_zone(size_t green, |
325 double log_buffer_scan_time, |
330 double logged_cards_scan_time, |
326 size_t processed_log_buffers, |
331 size_t processed_logged_cards, |
327 double goal_ms) { |
332 double goal_ms) { |
328 // Adjust green zone based on whether we're meeting the time goal. |
333 // Adjust green zone based on whether we're meeting the time goal. |
329 // Limit to max_green_zone. |
334 // Limit to max_green_zone. |
330 const double inc_k = 1.1, dec_k = 0.9; |
335 const double inc_k = 1.1, dec_k = 0.9; |
331 if (log_buffer_scan_time > goal_ms) { |
336 if (logged_cards_scan_time > goal_ms) { |
332 if (green > 0) { |
337 if (green > 0) { |
333 green = static_cast<size_t>(green * dec_k); |
338 green = static_cast<size_t>(green * dec_k); |
334 } |
339 } |
335 } else if (log_buffer_scan_time < goal_ms && |
340 } else if (logged_cards_scan_time < goal_ms && |
336 processed_log_buffers > green) { |
341 processed_logged_cards > green) { |
337 green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0)); |
342 green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0)); |
338 green = MIN2(green, max_green_zone); |
343 green = MIN2(green, max_green_zone); |
339 } |
344 } |
340 return green; |
345 return green; |
341 } |
346 } |
348 |
353 |
349 static size_t calc_new_red_zone(size_t green, size_t yellow) { |
354 static size_t calc_new_red_zone(size_t green, size_t yellow) { |
350 return MIN2(yellow + (yellow - green), max_red_zone); |
355 return MIN2(yellow + (yellow - green), max_red_zone); |
351 } |
356 } |
352 |
357 |
353 void G1ConcurrentRefine::update_zones(double log_buffer_scan_time, |
358 void G1ConcurrentRefine::update_zones(double logged_cards_scan_time, |
354 size_t processed_log_buffers, |
359 size_t processed_logged_cards, |
355 double goal_ms) { |
360 double goal_ms) { |
356 log_trace( CTRL_TAGS )("Updating Refinement Zones: " |
361 log_trace( CTRL_TAGS )("Updating Refinement Zones: " |
357 "log buffer scan time: %.3fms, " |
362 "logged cards scan time: %.3fms, " |
358 "processed buffers: " SIZE_FORMAT ", " |
363 "processed cards: " SIZE_FORMAT ", " |
359 "goal time: %.3fms", |
364 "goal time: %.3fms", |
360 log_buffer_scan_time, |
365 logged_cards_scan_time, |
361 processed_log_buffers, |
366 processed_logged_cards, |
362 goal_ms); |
367 goal_ms); |
363 |
368 |
364 _green_zone = calc_new_green_zone(_green_zone, |
369 _green_zone = calc_new_green_zone(_green_zone, |
365 log_buffer_scan_time, |
370 logged_cards_scan_time, |
366 processed_log_buffers, |
371 processed_logged_cards, |
367 goal_ms); |
372 goal_ms); |
368 _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size); |
373 _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size); |
369 _red_zone = calc_new_red_zone(_green_zone, _yellow_zone); |
374 _red_zone = calc_new_red_zone(_green_zone, _yellow_zone); |
370 |
375 |
371 assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone); |
376 assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone); |
374 "yellow: " SIZE_FORMAT ", " |
379 "yellow: " SIZE_FORMAT ", " |
375 "red: " SIZE_FORMAT, |
380 "red: " SIZE_FORMAT, |
376 _green_zone, _yellow_zone, _red_zone); |
381 _green_zone, _yellow_zone, _red_zone); |
377 } |
382 } |
378 |
383 |
379 void G1ConcurrentRefine::adjust(double log_buffer_scan_time, |
384 void G1ConcurrentRefine::adjust(double logged_cards_scan_time, |
380 size_t processed_log_buffers, |
385 size_t processed_logged_cards, |
381 double goal_ms) { |
386 double goal_ms) { |
382 G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); |
387 G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); |
383 |
388 |
384 if (G1UseAdaptiveConcRefinement) { |
389 if (G1UseAdaptiveConcRefinement) { |
385 update_zones(log_buffer_scan_time, processed_log_buffers, goal_ms); |
390 update_zones(logged_cards_scan_time, processed_logged_cards, goal_ms); |
386 |
391 |
387 // Change the barrier params |
392 // Change the barrier params |
388 if (max_num_threads() == 0) { |
393 if (max_num_threads() == 0) { |
389 // Disable dcqs notification when there are no threads to notify. |
394 // Disable dcqs notification when there are no threads to notify. |
390 dcqs.set_process_completed_buffers_threshold(G1DirtyCardQueueSet::ProcessCompletedBuffersThresholdNever); |
395 dcqs.set_process_cards_threshold(G1DirtyCardQueueSet::ProcessCardsThresholdNever); |
391 } else { |
396 } else { |
392 // Worker 0 is the primary; wakeup is via dcqs notification. |
397 // Worker 0 is the primary; wakeup is via dcqs notification. |
393 STATIC_ASSERT(max_yellow_zone <= INT_MAX); |
398 STATIC_ASSERT(max_yellow_zone <= INT_MAX); |
394 size_t activate = activation_threshold(0); |
399 size_t activate = activation_threshold(0); |
395 dcqs.set_process_completed_buffers_threshold(activate); |
400 dcqs.set_process_cards_threshold(activate); |
396 } |
401 } |
397 dcqs.set_max_completed_buffers(red_zone()); |
402 dcqs.set_max_cards(red_zone()); |
398 } |
403 } |
399 |
404 |
400 size_t curr_queue_size = dcqs.num_completed_buffers(); |
405 size_t curr_queue_size = dcqs.num_cards(); |
401 if ((dcqs.max_completed_buffers() > 0) && |
406 if ((dcqs.max_cards() > 0) && |
402 (curr_queue_size >= yellow_zone())) { |
407 (curr_queue_size >= yellow_zone())) { |
403 dcqs.set_completed_buffers_padding(curr_queue_size); |
408 dcqs.set_max_cards_padding(curr_queue_size); |
404 } else { |
409 } else { |
405 dcqs.set_completed_buffers_padding(0); |
410 dcqs.set_max_cards_padding(0); |
406 } |
411 } |
407 dcqs.notify_if_necessary(); |
412 dcqs.notify_if_necessary(); |
408 } |
413 } |
409 |
414 |
410 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const { |
415 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const { |
428 } |
433 } |
429 |
434 |
430 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) { |
435 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) { |
431 G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); |
436 G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); |
432 |
437 |
433 size_t curr_buffer_num = dcqs.num_completed_buffers(); |
438 size_t curr_cards = dcqs.num_cards(); |
434 // If the number of the buffers falls down into the yellow zone, |
439 // If the number of the cards falls down into the yellow zone, |
435 // that means that the transition period after the evacuation pause has ended. |
440 // 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 |
441 // Since the value written to the DCQS is the same for all threads, there is no |
437 // need to synchronize. |
442 // need to synchronize. |
438 if (dcqs.completed_buffers_padding() > 0 && curr_buffer_num <= yellow_zone()) { |
443 if (dcqs.max_cards_padding() > 0 && curr_cards <= yellow_zone()) { |
439 dcqs.set_completed_buffers_padding(0); |
444 dcqs.set_max_cards_padding(0); |
440 } |
445 } |
441 |
446 |
442 maybe_activate_more_threads(worker_id, curr_buffer_num); |
447 maybe_activate_more_threads(worker_id, curr_cards); |
443 |
448 |
444 // Process the next buffer, if there are enough left. |
449 // Process the next buffer, if there are enough left. |
445 return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(), |
450 return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(), |
446 deactivation_threshold(worker_id)); |
451 deactivation_threshold(worker_id)); |
447 } |
452 } |