--- old/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp 2010-04-27 08:04:15.000000000 -0700 +++ new/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp 2010-04-27 08:04:15.000000000 -0700 @@ -969,3 +969,94 @@ } } #endif + +bool ParallelScavengeHeap::resize_by_free_ratio(bool isFullGC) { + if (MinHeapFreeRatio <= 0 && MaxHeapFreeRatio >= 100) { + // nothing to do in this case + return false; + } + + PSOldGen* old = old_gen(); + PSYoungGen* young = young_gen(); + + // On a major collection (isFullGC == true), resize the young and old gens. + // On a minor collection (isFullGC == false), resize the young gen only. + size_t capacity = young->capacity_in_bytes(); + size_t used = young->used_in_bytes(); + size_t init_size = young->init_gen_size(); + size_t max_size = young->max_size(); + if (isFullGC) { + capacity += old->capacity_in_bytes(); + used += old->used_in_bytes(); + init_size += old->init_gen_size(); + max_size += old->max_gen_size(); + } + + // Shrink + if (MaxHeapFreeRatio < 100) { + const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; + const double minimum_used_percentage = 1.0 - maximum_free_percentage; + const double max_tmp = used / minimum_used_percentage; + size_t maximum_desired_capacity = MIN2((size_t) max_tmp, max_size); + maximum_desired_capacity = MAX2(maximum_desired_capacity, init_size); + + if (PrintGC && Verbose) { + const double free_ratio = 1.0 - (double) used / capacity; + gclog_or_tty->print("Shrink by free ratio: "); + gclog_or_tty->print("capacity : " SIZE_FORMAT ", ", capacity); + gclog_or_tty->print("used : " SIZE_FORMAT ", ", used); + gclog_or_tty->print_cr("free ratio : %f.2", free_ratio); + } + + size_t free_bytes = capacity - used; + if (capacity > maximum_desired_capacity && free_bytes > 0) { + size_t shrink_bytes = capacity - maximum_desired_capacity; + if (isFullGC) { + size_t old_gen_free_bytes = old->capacity_in_bytes() - old->used_in_bytes(); + size_t old_gen_shrink_bytes = + (size_t) (shrink_bytes * ((double) old_gen_free_bytes / free_bytes)); + old->try_to_shrink_by(old_gen_shrink_bytes); + } + size_t young_gen_free_bytes = young->capacity_in_bytes() - young->used_in_bytes(); + size_t young_gen_shrink_bytes = + (size_t) (shrink_bytes * ((double) young_gen_free_bytes / free_bytes)); + young->try_to_shrink_by(young_gen_shrink_bytes); + return true; + } + } + + // Expand + if (MinHeapFreeRatio > 0) { + const double minimum_free_percentage = MinHeapFreeRatio / 100.0; + const double maximum_used_percentage = 1.0 - minimum_free_percentage; + const double min_tmp = used / maximum_used_percentage; + size_t minimum_desired_capacity = MIN2((size_t) min_tmp, max_size); + minimum_desired_capacity = MAX2(minimum_desired_capacity, init_size); + + if (PrintGC && Verbose) { + const double free_ratio = 1.0 - (double) used / capacity; + gclog_or_tty->print("Expand by free ratio: "); + gclog_or_tty->print("capacity : " SIZE_FORMAT ", ", capacity); + gclog_or_tty->print("used : " SIZE_FORMAT ", ", used); + gclog_or_tty->print_cr("free ratio : %f.2", free_ratio); + } + + size_t available_bytes = max_size - capacity; + if (capacity < minimum_desired_capacity && available_bytes > 0) { + size_t expand_bytes = minimum_desired_capacity - capacity; + if (isFullGC) { + size_t old_gen_available_bytes = old->max_gen_size() - old->capacity_in_bytes(); + size_t old_gen_expand_bytes = + (size_t) (expand_bytes * ((double) old_gen_available_bytes / available_bytes)); + old->try_to_expand_by(old_gen_expand_bytes); + } + size_t young_gen_available_bytes = young->max_size() - young->capacity_in_bytes(); + size_t young_gen_expand_bytes = + (size_t) (expand_bytes * ((double) young_gen_available_bytes / available_bytes)); + young->try_to_expand_by(young_gen_expand_bytes); + return true; + } + } + + return false; +}