diff --git a/src/share/vm/memory/collectorPolicy.cpp b/src/share/vm/memory/collectorPolicy.cpp index 204011b689e75f01bb44dc469c4af9987f12b3ec..e7dc6d7cc0645e482364321b1d703ebc8aca439f 100644 --- a/src/share/vm/memory/collectorPolicy.cpp +++ b/src/share/vm/memory/collectorPolicy.cpp @@ -450,18 +450,20 @@ void GenCollectorPolicy::initialize_size_info() { _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. + 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. @@ -989,3 +991,110 @@ void MarkSweepPolicy::initialize_gc_policy_counters() { _gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 3); } } + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT +// Testing that the NewSize flag is handled correct is hard because it +// depends on so many other configurable variables. This test only tries to +// verify that there are some basic rules for NewSize honored by the policies. +class TestGenCollectorPolicy { +public: + static void test() { + size_t flag_value; + + save_flags(); + + // Set some limits that makes the math simple. + FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M); + FLAG_SET_ERGO(uintx, InitialHeapSize, 120 * M); + Arguments::set_min_heap_size(40 * M); + + // If NewSize is set on the command line, it should be used + // for both min and initial young size if less than min heap. + flag_value = 20 * M; + FLAG_SET_CMDLINE(uintx, NewSize, flag_value); + verify_min(flag_value); + verify_initial(flag_value); + + // If NewSize is set on command line, but is larger than the min + // heap size, it should only be used for initial young size. + flag_value = 80 * M; + FLAG_SET_CMDLINE(uintx, NewSize, flag_value); + verify_initial(flag_value); + + // If NewSize has been ergonomically set, the collector policy + // should use it for min but calculate the initial young size + // using NewRatio. + flag_value = 20 * M; + FLAG_SET_ERGO(uintx, NewSize, flag_value); + verify_min(flag_value); + verify_scaled_initial(InitialHeapSize); + + restore_flags(); + + } + + static void verify_min(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.min_gen0_size() <= expected, err_msg("%zu > %zu", msp.min_gen0_size(), expected)); + } + + static void verify_initial(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected)); + } + + static void verify_scaled_initial(size_t initial_heap_size) { + MarkSweepPolicy msp; + msp.initialize_all(); + + size_t expected = msp.scale_by_NewRatio_aligned(initial_heap_size); + assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected)); + assert(FLAG_IS_ERGO(NewSize) && NewSize == expected, + err_msg("NewSize should have been set ergonomically to %zu, but was %zu", expected, NewSize)); + } + +private: + static size_t original_InitialHeapSize; + static size_t original_MaxHeapSize; + static size_t original_MaxNewSize; + static size_t original_MinHeapDeltaBytes; + static size_t original_NewSize; + static size_t original_OldSize; + + static void save_flags() { + original_InitialHeapSize = InitialHeapSize; + original_MaxHeapSize = MaxHeapSize; + original_MaxNewSize = MaxNewSize; + original_MinHeapDeltaBytes = MinHeapDeltaBytes; + original_NewSize = NewSize; + original_OldSize = OldSize; + } + + static void restore_flags() { + InitialHeapSize = original_InitialHeapSize; + MaxHeapSize = original_MaxHeapSize; + MaxNewSize = original_MaxNewSize; + MinHeapDeltaBytes = original_MinHeapDeltaBytes; + NewSize = original_NewSize; + OldSize = original_OldSize; + } +}; + +size_t TestGenCollectorPolicy::original_InitialHeapSize = 0; +size_t TestGenCollectorPolicy::original_MaxHeapSize = 0; +size_t TestGenCollectorPolicy::original_MaxNewSize = 0; +size_t TestGenCollectorPolicy::original_MinHeapDeltaBytes = 0; +size_t TestGenCollectorPolicy::original_NewSize = 0; +size_t TestGenCollectorPolicy::original_OldSize = 0; + +void TestNewSize_test() { + TestGenCollectorPolicy::test(); +} + +#endif diff --git a/src/share/vm/memory/collectorPolicy.hpp b/src/share/vm/memory/collectorPolicy.hpp index b72030113c4604b82d890b0f77c03cce29a11d2c..e0982bafc38894cf325146345ac7f8e97f7fb2e0 100644 --- a/src/share/vm/memory/collectorPolicy.hpp +++ b/src/share/vm/memory/collectorPolicy.hpp @@ -220,6 +220,7 @@ class ClearedAllSoftRefs : public StackObj { }; class GenCollectorPolicy : public CollectorPolicy { +friend class TestGenCollectorPolicy; protected: size_t _min_gen0_size; size_t _initial_gen0_size; diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp index eb7de64f4cdae126662a4bf6c45ac5aad1446b93..3bb8be766ae80d40d60f895060016445a5631f62 100644 --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -5080,6 +5080,7 @@ void TestVirtualSpace_test(); void TestMetaspaceAux_test(); void TestMetachunk_test(); void TestVirtualSpaceNode_test(); +void TestNewSize_test(); #if INCLUDE_ALL_GCS void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); @@ -5102,6 +5103,7 @@ void execute_internal_vm_tests() { run_unit_test(QuickSort::test_quick_sort()); run_unit_test(AltHashing::test_alt_hash()); run_unit_test(test_loggc_filename()); + run_unit_test(TestNewSize_test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif