// Values set on the command line win over any ergonomically // set command line parameters. // Ergonomic choice of parameters are done before this // method is called. Values for command line parameters such as NewSize // and MaxNewSize feed those ergonomic choices into this method. // This method makes the final generation sizings consistent with // themselves and with overall heap sizings. // In the absence of explicitly set command line flags, policies // such as the use of NewRatio are used to size the generation. void GenCollectorPolicy::initialize_size_info() { CollectorPolicy::initialize_size_info(); // min_alignment() is used for alignment within a generation. // There is additional alignment done down stream for some // collectors that sometimes causes unwanted rounding up of // generations sizes. // Determine maximum size of gen0 size_t max_new_size = 0; if (FLAG_IS_CMDLINE(MaxNewSize)) { if (MaxNewSize < min_alignment()) { max_new_size = min_alignment(); } else if (MaxNewSize >= max_heap_byte_size()) { max_new_size = align_size_down(max_heap_byte_size() - min_alignment(), min_alignment()); warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or " "greater than the entire heap (" SIZE_FORMAT "k). A " "new generation size of " SIZE_FORMAT "k will be used.", MaxNewSize/K, max_heap_byte_size()/K, max_new_size/K); } else { max_new_size = align_size_down(MaxNewSize, min_alignment()); } // The case for FLAG_IS_ERGO(MaxNewSize) could be treated // specially at this point to just use an ergonomically set // MaxNewSize to set max_new_size. For cases with small // heaps such a policy often did not work because the MaxNewSize // was larger than the entire heap. The interpretation given // to ergonomically set flags is that the flags are set // by different collectors for their own special needs but // are not allowed to badly shape the heap. This allows the // different collectors to decide what's best for themselves // without having to factor in the overall heap shape. It // can be the case in the future that the collectors would // only make "wise" ergonomics choices and this policy could // just accept those choices. The choices currently made are // not always "wise". } else { max_new_size = scale_by_NewRatio_aligned(max_heap_byte_size()); // Bound the maximum size by NewSize below (since it historically // would have been NewSize and because the NewRatio calculation could // yield a size that is too small) and bound it by MaxNewSize above. // Ergonomics plays here by previously calculating the desired // NewSize and MaxNewSize. max_new_size = MIN2(MAX2(max_new_size, (size_t)NewSize), (size_t)MaxNewSize); } assert(max_new_size > 0, "All paths should set max_new_size"); // Given the maximum gen0 size, determine the initial and // minimum sizes. if (max_heap_byte_size() == min_heap_byte_size()) { // The maximum and minimum heap sizes are the same so // the generations minimum and initial must be the // same as its maximum. set_min_gen0_size(max_new_size); set_initial_gen0_size(max_new_size); set_max_gen0_size(max_new_size); } else { size_t desired_new_size = 0; if (!FLAG_IS_DEFAULT(NewSize)) { // If NewSize is set ergonomically (for example by cms), it // would make sense to use it. If it is used, also use it // to set the initial size. Although there is no reason // the minimum size and the initial size have to be the same, // the current implementation gets into trouble during the calculation // of the tenured generation sizes if they are different. // Note that this makes the initial size and the minimum size // generally small compared to the NewRatio calculation. _min_gen0_size = NewSize; desired_new_size = NewSize; max_new_size = MAX2(max_new_size, (size_t) NewSize); } else { // For the case where NewSize is the default, use NewRatio // to size the minimum and initial generation sizes. // Use the default NewSize as the floor for these values. If // NewRatio is overly large, the resulting sizes can be too // small. _min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()), (size_t) NewSize); desired_new_size = MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()), (size_t) NewSize); } assert(_min_gen0_size > 0, "Sanity check"); set_initial_gen0_size(desired_new_size); set_max_gen0_size(max_new_size); // At this point the desirable initial and minimum sizes have been // determined without regard to the maximum sizes. // Bound the sizes by the corresponding overall heap sizes. set_min_gen0_size( bound_minus_alignment(_min_gen0_size, min_heap_byte_size())); set_initial_gen0_size( bound_minus_alignment(_initial_gen0_size, initial_heap_byte_size())); set_max_gen0_size( bound_minus_alignment(_max_gen0_size, max_heap_byte_size())); // At this point all three sizes have been checked against the // maximum sizes but have not been checked for consistency // among the three. // Final check min <= initial <= max set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size)); set_initial_gen0_size( MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size)); set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size)); } if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); } }
// Values set on the command line win over any ergonomically // set command line parameters. // Ergonomic choice of parameters are done before this // method is called. Values for command line parameters such as NewSize // and MaxNewSize feed those ergonomic choices into this method. // This method makes the final generation sizings consistent with // themselves and with overall heap sizings. // In the absence of explicitly set command line flags, policies // such as the use of NewRatio are used to size the generation. void GenCollectorPolicy::initialize_size_info() { CollectorPolicy::initialize_size_info(); // _space_alignment is used for alignment within a generation. // There is additional alignment done down stream for some // collectors that sometimes causes unwanted rounding up of // generations sizes. // Determine maximum size of gen0 size_t max_new_size = 0; if (!FLAG_IS_DEFAULT(MaxNewSize)) { max_new_size = MaxNewSize; } else { max_new_size = scale_by_NewRatio_aligned(_max_heap_byte_size); // Bound the maximum size by NewSize below (since it historically // would have been NewSize and because the NewRatio calculation could // yield a size that is too small) and bound it by MaxNewSize above. // Ergonomics plays here by previously calculating the desired // NewSize and MaxNewSize. max_new_size = MIN2(MAX2(max_new_size, NewSize), MaxNewSize); } assert(max_new_size > 0, "All paths should set max_new_size"); // Given the maximum gen0 size, determine the initial and // minimum gen0 sizes. if (_max_heap_byte_size == _min_heap_byte_size) { // The maximum and minimum heap sizes are the same so // the generations minimum and initial must be the // same as its maximum. _min_gen0_size = max_new_size; _initial_gen0_size = max_new_size; _max_gen0_size = max_new_size; } else { size_t desired_new_size = 0; if (FLAG_IS_CMDLINE(NewSize)) { // If NewSize is set on the command line, we must use it as // the initial size and it also makes sense to use it as the // lower limit. _min_gen0_size = NewSize; desired_new_size = NewSize; max_new_size = MAX2(max_new_size, NewSize); } else if (FLAG_IS_ERGO(NewSize)) { // If NewSize is set ergonomically, we should use it as a lower // limit, but use NewRatio to calculate the initial size. _min_gen0_size = NewSize; desired_new_size = MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); max_new_size = MAX2(max_new_size, NewSize); } else { // For the case where NewSize is the default, use NewRatio // to size the minimum and initial generation sizes. // Use the default NewSize as the floor for these values. If // NewRatio is overly large, the resulting sizes can be too // small. _min_gen0_size = MAX2(scale_by_NewRatio_aligned(_min_heap_byte_size), NewSize); desired_new_size = MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); } assert(_min_gen0_size > 0, "Sanity check"); _initial_gen0_size = desired_new_size; _max_gen0_size = max_new_size; // At this point the desirable initial and minimum sizes have been // determined without regard to the maximum sizes. // Bound the sizes by the corresponding overall heap sizes. _min_gen0_size = bound_minus_alignment(_min_gen0_size, _min_heap_byte_size); _initial_gen0_size = bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size); _max_gen0_size = bound_minus_alignment(_max_gen0_size, _max_heap_byte_size); // At this point all three sizes have been checked against the // maximum sizes but have not been checked for consistency // among the three. // Final check min <= initial <= max _min_gen0_size = MIN2(_min_gen0_size, _max_gen0_size); _initial_gen0_size = MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size); _min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size); } // Write back to flags if necessary if (NewSize != _initial_gen0_size) { FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size); } if (MaxNewSize != _max_gen0_size) { FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size); } if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, _min_gen0_size, _initial_gen0_size, _max_gen0_size); } DEBUG_ONLY(GenCollectorPolicy::assert_size_info();) }
// Minimum sizes of the generations may be different than // the initial sizes. An inconsistency is permitted here // in the total size that can be specified explicitly by // command line specification of OldSize and NewSize and // also a command line specification of -Xms. Issue a warning // but allow the values to pass. void GenCollectorPolicy::initialize_size_info() { CollectorPolicy::initialize_size_info(); _initial_young_size = NewSize; _max_young_size = MaxNewSize; _initial_old_size = OldSize; // Determine maximum size of the young generation. if (FLAG_IS_DEFAULT(MaxNewSize)) { _max_young_size = scale_by_NewRatio_aligned(_max_heap_byte_size); // Bound the maximum size by NewSize below (since it historically // would have been NewSize and because the NewRatio calculation could // yield a size that is too small) and bound it by MaxNewSize above. // Ergonomics plays here by previously calculating the desired // NewSize and MaxNewSize. _max_young_size = MIN2(MAX2(_max_young_size, _initial_young_size), MaxNewSize); } // Given the maximum young size, determine the initial and // minimum young sizes. if (_max_heap_byte_size == _initial_heap_byte_size) { // The maximum and initial heap sizes are the same so the generation's // initial size must be the same as it maximum size. Use NewSize as the // size if set on command line. _max_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : _max_young_size; _initial_young_size = _max_young_size; // Also update the minimum size if min == initial == max. if (_max_heap_byte_size == _min_heap_byte_size) { _min_young_size = _max_young_size; } } else { if (FLAG_IS_CMDLINE(NewSize)) { // If NewSize is set on the command line, we should use it as // the initial size, but make sure it is within the heap bounds. _initial_young_size = MIN2(_max_young_size, bound_minus_alignment(NewSize, _initial_heap_byte_size)); _min_young_size = bound_minus_alignment(_initial_young_size, _min_heap_byte_size); } else { // For the case where NewSize is not set on the command line, use // NewRatio to size the initial generation size. Use the current // NewSize as the floor, because if NewRatio is overly large, the resulting // size can be too small. _initial_young_size = MIN2(_max_young_size, MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize)); } } log_trace(gc, heap)("1: Minimum young " SIZE_FORMAT " Initial young " SIZE_FORMAT " Maximum young " SIZE_FORMAT, _min_young_size, _initial_young_size, _max_young_size); // At this point the minimum, initial and maximum sizes // of the overall heap and of the young generation have been determined. // The maximum old size can be determined from the maximum young // and maximum heap size since no explicit flags exist // for setting the old generation maximum. _max_old_size = MAX2(_max_heap_byte_size - _max_young_size, _gen_alignment); // If no explicit command line flag has been set for the // old generation size, use what is left. if (!FLAG_IS_CMDLINE(OldSize)) { // The user has not specified any value but the ergonomics // may have chosen a value (which may or may not be consistent // with the overall heap size). In either case make // the minimum, maximum and initial sizes consistent // with the young sizes and the overall heap sizes. _min_old_size = _gen_alignment; _initial_old_size = MIN2(_max_old_size, MAX2(_initial_heap_byte_size - _initial_young_size, _min_old_size)); // _max_old_size has already been made consistent above. } else { // OldSize has been explicitly set on the command line. Use it // for the initial size but make sure the minimum allow a young // generation to fit as well. // If the user has explicitly set an OldSize that is inconsistent // with other command line flags, issue a warning. // The generation minimums and the overall heap minimum should // be within one generation alignment. if (_initial_old_size > _max_old_size) { log_warning(gc, ergo)("Inconsistency between maximum heap size and maximum " "generation sizes: using maximum heap = " SIZE_FORMAT ", -XX:OldSize flag is being ignored", _max_heap_byte_size); _initial_old_size = _max_old_size; } _min_old_size = MIN2(_initial_old_size, _min_heap_byte_size - _min_young_size); } // The initial generation sizes should match the initial heap size, // if not issue a warning and resize the generations. This behavior // differs from JDK8 where the generation sizes have higher priority // than the initial heap size. if ((_initial_old_size + _initial_young_size) != _initial_heap_byte_size) { log_warning(gc, ergo)("Inconsistency between generation sizes and heap size, resizing " "the generations to fit the heap."); size_t desired_young_size = _initial_heap_byte_size - _initial_old_size; if (_initial_heap_byte_size < _initial_old_size) { // Old want all memory, use minimum for young and rest for old _initial_young_size = _min_young_size; _initial_old_size = _initial_heap_byte_size - _min_young_size; } else if (desired_young_size > _max_young_size) { // Need to increase both young and old generation _initial_young_size = _max_young_size; _initial_old_size = _initial_heap_byte_size - _max_young_size; } else if (desired_young_size < _min_young_size) { // Need to decrease both young and old generation _initial_young_size = _min_young_size; _initial_old_size = _initial_heap_byte_size - _min_young_size; } else { // The young generation boundaries allow us to only update the // young generation. _initial_young_size = desired_young_size; } log_trace(gc, heap)("2: Minimum young " SIZE_FORMAT " Initial young " SIZE_FORMAT " Maximum young " SIZE_FORMAT, _min_young_size, _initial_young_size, _max_young_size); } // Write back to flags if necessary. if (NewSize != _initial_young_size) { FLAG_SET_ERGO(size_t, NewSize, _initial_young_size); } if (MaxNewSize != _max_young_size) { FLAG_SET_ERGO(size_t, MaxNewSize, _max_young_size); } if (OldSize != _initial_old_size) { FLAG_SET_ERGO(size_t, OldSize, _initial_old_size); } log_trace(gc, heap)("Minimum old " SIZE_FORMAT " Initial old " SIZE_FORMAT " Maximum old " SIZE_FORMAT, _min_old_size, _initial_old_size, _max_old_size); DEBUG_ONLY(GenCollectorPolicy::assert_size_info();) }