Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 1973:631f79e71e90
6974966: G1: unnecessary direct-to-old allocations
Summary: This change revamps the slow allocation path of G1. Improvements include the following: a) Allocations directly to old regions are now totally banned. G1 now only allows allocations out of young regions (with the only exception being humongous regions). b) The thread that allocates a new region (which is now guaranteed to be young) does not dirty all its cards. Each thread that successfully allocates out of a young region is now responsible for dirtying the cards that corresponding to the "block" that just got allocated. c) allocate_new_tlab() and mem_allocate() are now implemented differently and TLAB allocations are only done by allocate_new_tlab(). d) If a thread schedules an evacuation pause in order to satisfy an allocation request, it will perform the allocation at the end of the safepoint so that the thread that initiated the GC also gets "first pick" of any space made available by the GC. e) If a thread is unable to allocate a humongous object it will schedule an evacuation pause in case it reclaims enough regions so that the humongous allocation can be satisfied aftewards. f) The G1 policy is more careful to set the young list target length to be the survivor number +1. g) Lots of code tidy up, removal, refactoring to make future changes easier.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Tue, 24 Aug 2010 17:24:33 -0400 |
parents | f95d63e2154a |
children | 016a3628c885 |
comparison
equal
deleted
inserted
replaced
1972:f95d63e2154a | 1973:631f79e71e90 |
---|---|
456 | 456 |
457 if (_alloc_rate_ms_seq->num() > 3) { | 457 if (_alloc_rate_ms_seq->num() > 3) { |
458 double now_sec = os::elapsedTime(); | 458 double now_sec = os::elapsedTime(); |
459 double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; | 459 double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; |
460 double alloc_rate_ms = predict_alloc_rate_ms(); | 460 double alloc_rate_ms = predict_alloc_rate_ms(); |
461 int min_regions = (int) ceil(alloc_rate_ms * when_ms); | 461 size_t min_regions = (size_t) ceil(alloc_rate_ms * when_ms); |
462 int current_region_num = (int) _g1->young_list()->length(); | 462 size_t current_region_num = _g1->young_list()->length(); |
463 _young_list_min_length = min_regions + current_region_num; | 463 _young_list_min_length = min_regions + current_region_num; |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 void G1CollectorPolicy::calculate_young_list_target_length() { | 467 void G1CollectorPolicy::calculate_young_list_target_length() { |
471 } else { | 471 } else { |
472 if (full_young_gcs()) | 472 if (full_young_gcs()) |
473 _young_list_target_length = _young_list_fixed_length; | 473 _young_list_target_length = _young_list_fixed_length; |
474 else | 474 else |
475 _young_list_target_length = _young_list_fixed_length / 2; | 475 _young_list_target_length = _young_list_fixed_length / 2; |
476 | 476 } |
477 _young_list_target_length = MAX2(_young_list_target_length, (size_t)1); | 477 |
478 } | 478 // Make sure we allow the application to allocate at least one |
479 // region before we need to do a collection again. | |
480 size_t min_length = _g1->young_list()->length() + 1; | |
481 _young_list_target_length = MAX2(_young_list_target_length, min_length); | |
479 calculate_survivors_policy(); | 482 calculate_survivors_policy(); |
480 } | 483 } |
481 | 484 |
482 void G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths) { | 485 void G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths) { |
483 guarantee( adaptive_young_list_length(), "pre-condition" ); | 486 guarantee( adaptive_young_list_length(), "pre-condition" ); |
566 } | 569 } |
567 // and we're done! | 570 // and we're done! |
568 | 571 |
569 // we should have at least one region in the target young length | 572 // we should have at least one region in the target young length |
570 _young_list_target_length = | 573 _young_list_target_length = |
571 MAX2((size_t) 1, final_young_length + _recorded_survivor_regions); | 574 final_young_length + _recorded_survivor_regions; |
572 | 575 |
573 // let's keep an eye of how long we spend on this calculation | 576 // let's keep an eye of how long we spend on this calculation |
574 // right now, I assume that we'll print it when we need it; we | 577 // right now, I assume that we'll print it when we need it; we |
575 // should really adde it to the breakdown of a pause | 578 // should really adde it to the breakdown of a pause |
576 double end_time_sec = os::elapsedTime(); | 579 double end_time_sec = os::elapsedTime(); |
615 // leave this in for debugging, just in case | 618 // leave this in for debugging, just in case |
616 gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT | 619 gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT |
617 _young_list_min_length); | 620 _young_list_min_length); |
618 #endif // TRACE_CALC_YOUNG_LENGTH | 621 #endif // TRACE_CALC_YOUNG_LENGTH |
619 // we'll do the pause as soon as possible by choosing the minimum | 622 // we'll do the pause as soon as possible by choosing the minimum |
620 _young_list_target_length = | 623 _young_list_target_length = _young_list_min_length; |
621 MAX2(_young_list_min_length, (size_t) 1); | |
622 } | 624 } |
623 | 625 |
624 _rs_lengths_prediction = rs_lengths; | 626 _rs_lengths_prediction = rs_lengths; |
625 } | 627 } |
626 | 628 |
799 _free_regions_at_end_of_collection = _g1->free_regions(); | 801 _free_regions_at_end_of_collection = _g1->free_regions(); |
800 // Reset survivors SurvRateGroup. | 802 // Reset survivors SurvRateGroup. |
801 _survivor_surv_rate_group->reset(); | 803 _survivor_surv_rate_group->reset(); |
802 calculate_young_list_min_length(); | 804 calculate_young_list_min_length(); |
803 calculate_young_list_target_length(); | 805 calculate_young_list_target_length(); |
804 } | 806 } |
805 | 807 |
806 void G1CollectorPolicy::record_before_bytes(size_t bytes) { | 808 void G1CollectorPolicy::record_before_bytes(size_t bytes) { |
807 _bytes_in_to_space_before_gc += bytes; | 809 _bytes_in_to_space_before_gc += bytes; |
808 } | 810 } |
809 | 811 |
822 gclog_or_tty->print("[GC pause"); | 824 gclog_or_tty->print("[GC pause"); |
823 if (in_young_gc_mode()) | 825 if (in_young_gc_mode()) |
824 gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial"); | 826 gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial"); |
825 } | 827 } |
826 | 828 |
827 assert(_g1->used_regions() == _g1->recalculate_used_regions(), | 829 assert(_g1->used() == _g1->recalculate_used(), |
828 "sanity"); | 830 err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT, |
829 assert(_g1->used() == _g1->recalculate_used(), "sanity"); | 831 _g1->used(), _g1->recalculate_used())); |
830 | 832 |
831 double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; | 833 double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; |
832 _all_stop_world_times_ms->add(s_w_t_ms); | 834 _all_stop_world_times_ms->add(s_w_t_ms); |
833 _stop_world_start = 0.0; | 835 _stop_world_start = 0.0; |
834 | 836 |
2264 _short_lived_surv_rate_group->print_surv_rate_summary(); | 2266 _short_lived_surv_rate_group->print_surv_rate_summary(); |
2265 // add this call for any other surv rate groups | 2267 // add this call for any other surv rate groups |
2266 #endif // PRODUCT | 2268 #endif // PRODUCT |
2267 } | 2269 } |
2268 | 2270 |
2269 bool | 2271 void |
2270 G1CollectorPolicy::should_add_next_region_to_young_list() { | 2272 G1CollectorPolicy::update_region_num(bool young) { |
2271 assert(in_young_gc_mode(), "should be in young GC mode"); | 2273 if (young) { |
2272 bool ret; | |
2273 size_t young_list_length = _g1->young_list()->length(); | |
2274 size_t young_list_max_length = _young_list_target_length; | |
2275 if (G1FixedEdenSize) { | |
2276 young_list_max_length -= _max_survivor_regions; | |
2277 } | |
2278 if (young_list_length < young_list_max_length) { | |
2279 ret = true; | |
2280 ++_region_num_young; | 2274 ++_region_num_young; |
2281 } else { | 2275 } else { |
2282 ret = false; | |
2283 ++_region_num_tenured; | 2276 ++_region_num_tenured; |
2284 } | 2277 } |
2285 | |
2286 return ret; | |
2287 } | 2278 } |
2288 | 2279 |
2289 #ifndef PRODUCT | 2280 #ifndef PRODUCT |
2290 // for debugging, bit of a hack... | 2281 // for debugging, bit of a hack... |
2291 static char* | 2282 static char* |
2323 _tenuring_threshold = MaxTenuringThreshold; | 2314 _tenuring_threshold = MaxTenuringThreshold; |
2324 } else { | 2315 } else { |
2325 _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( | 2316 _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( |
2326 HeapRegion::GrainWords * _max_survivor_regions); | 2317 HeapRegion::GrainWords * _max_survivor_regions); |
2327 } | 2318 } |
2328 } | |
2329 | |
2330 bool | |
2331 G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t | |
2332 word_size) { | |
2333 assert(_g1->regions_accounted_for(), "Region leakage!"); | |
2334 double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; | |
2335 | |
2336 size_t young_list_length = _g1->young_list()->length(); | |
2337 size_t young_list_max_length = _young_list_target_length; | |
2338 if (G1FixedEdenSize) { | |
2339 young_list_max_length -= _max_survivor_regions; | |
2340 } | |
2341 bool reached_target_length = young_list_length >= young_list_max_length; | |
2342 | |
2343 if (in_young_gc_mode()) { | |
2344 if (reached_target_length) { | |
2345 assert( young_list_length > 0 && _g1->young_list()->length() > 0, | |
2346 "invariant" ); | |
2347 return true; | |
2348 } | |
2349 } else { | |
2350 guarantee( false, "should not reach here" ); | |
2351 } | |
2352 | |
2353 return false; | |
2354 } | 2319 } |
2355 | 2320 |
2356 #ifndef PRODUCT | 2321 #ifndef PRODUCT |
2357 class HRSortIndexIsOKClosure: public HeapRegionClosure { | 2322 class HRSortIndexIsOKClosure: public HeapRegionClosure { |
2358 CollectionSetChooser* _chooser; | 2323 CollectionSetChooser* _chooser; |