1 /* 2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "gc/parallel/parallelArguments.hpp" 28 #include "gc/parallel/parallelScavengeHeap.hpp" 29 #include "gc/shared/adaptiveSizePolicy.hpp" 30 #include "gc/shared/gcArguments.hpp" 31 #include "gc/shared/genArguments.hpp" 32 #include "gc/shared/workerPolicy.hpp" 33 #include "logging/log.hpp" 34 #include "runtime/globals.hpp" 35 #include "runtime/globals_extension.hpp" 36 #include "runtime/java.hpp" 37 #include "utilities/defaultStream.hpp" 38 #include "utilities/powerOfTwo.hpp" 39 40 static const double MaxRamFractionForYoung = 0.8; 41 42 size_t ParallelArguments::conservative_max_heap_alignment() { 43 return compute_heap_alignment(); 44 } 45 46 void ParallelArguments::initialize() { 47 GCArguments::initialize(); 48 assert(UseParallelGC, "Error"); 49 50 // If no heap maximum was requested explicitly, use some reasonable fraction 51 // of the physical memory, up to a maximum of 1GB. 52 FLAG_SET_DEFAULT(ParallelGCThreads, 53 WorkerPolicy::parallel_worker_threads()); 54 if (ParallelGCThreads == 0) { 55 jio_fprintf(defaultStream::error_stream(), 56 "The Parallel GC can not be combined with -XX:ParallelGCThreads=0\n"); 57 vm_exit(1); 58 } 59 60 if (UseAdaptiveSizePolicy) { 61 // We don't want to limit adaptive heap sizing's freedom to adjust the heap 62 // unless the user actually sets these flags. 63 if (FLAG_IS_DEFAULT(MinHeapFreeRatio)) { 64 FLAG_SET_DEFAULT(MinHeapFreeRatio, 0); 65 } 66 if (FLAG_IS_DEFAULT(MaxHeapFreeRatio)) { 67 FLAG_SET_DEFAULT(MaxHeapFreeRatio, 100); 68 } 69 } 70 71 // If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the 72 // SurvivorRatio has been set, reset their default values to SurvivorRatio + 73 // 2. By doing this we make SurvivorRatio also work for Parallel Scavenger. 74 // See CR 6362902 for details. 75 if (!FLAG_IS_DEFAULT(SurvivorRatio)) { 76 if (FLAG_IS_DEFAULT(InitialSurvivorRatio)) { 77 FLAG_SET_DEFAULT(InitialSurvivorRatio, SurvivorRatio + 2); 78 } 79 if (FLAG_IS_DEFAULT(MinSurvivorRatio)) { 80 FLAG_SET_DEFAULT(MinSurvivorRatio, SurvivorRatio + 2); 81 } 82 } 83 84 // Par compact uses lower default values since they are treated as 85 // minimums. These are different defaults because of the different 86 // interpretation and are not ergonomically set. 87 if (FLAG_IS_DEFAULT(MarkSweepDeadRatio)) { 88 FLAG_SET_DEFAULT(MarkSweepDeadRatio, 1); 89 } 90 } 91 92 // The alignment used for boundary between young gen and old gen 93 static size_t default_gen_alignment() { 94 return 64 * K * HeapWordSize; 95 } 96 97 void ParallelArguments::initialize_alignments() { 98 SpaceAlignment = GenAlignment = default_gen_alignment(); 99 HeapAlignment = compute_heap_alignment(); 100 } 101 102 void ParallelArguments::initialize_heap_flags_and_sizes_one_pass() { 103 // Do basic sizing work 104 GenArguments::initialize_heap_flags_and_sizes(); 105 106 // The survivor ratio's are calculated "raw", unlike the 107 // default gc, which adds 2 to the ratio value. We need to 108 // make sure the values are valid before using them. 109 if (MinSurvivorRatio < 3) { 110 FLAG_SET_ERGO(MinSurvivorRatio, 3); 111 } 112 113 if (InitialSurvivorRatio < 3) { 114 FLAG_SET_ERGO(InitialSurvivorRatio, 3); 115 } 116 } 117 118 void ParallelArguments::initialize_heap_flags_and_sizes() { 119 if (is_heterogeneous_heap()) { 120 initialize_heterogeneous(); 121 } 122 123 initialize_heap_flags_and_sizes_one_pass(); 124 125 const size_t max_page_sz = os::page_size_for_region_aligned(MaxHeapSize, 8); 126 const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old 127 const size_t min_page_sz = os::page_size_for_region_aligned(MinHeapSize, min_pages); 128 const size_t page_sz = MIN2(max_page_sz, min_page_sz); 129 130 // Can a page size be something else than a power of two? 131 assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2"); 132 size_t new_alignment = align_up(page_sz, GenAlignment); 133 if (new_alignment != GenAlignment) { 134 GenAlignment = new_alignment; 135 SpaceAlignment = new_alignment; 136 // Redo everything from the start 137 initialize_heap_flags_and_sizes_one_pass(); 138 } 139 } 140 141 // Check the available dram memory to limit NewSize and MaxNewSize before 142 // calling base class initialize_flags(). 143 void ParallelArguments::initialize_heterogeneous() { 144 FormatBuffer<100> calc_str(""); 145 146 julong phys_mem; 147 // If MaxRam is specified, we use that as maximum physical memory available. 148 if (FLAG_IS_DEFAULT(MaxRAM)) { 149 phys_mem = os::physical_memory(); 150 calc_str.append("Physical_Memory"); 151 } else { 152 phys_mem = (julong)MaxRAM; 153 calc_str.append("MaxRAM"); 154 } 155 156 julong reasonable_max = phys_mem; 157 158 // If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate 159 // reasonable max size of young generation. 160 if (!FLAG_IS_DEFAULT(MaxRAMFraction)) { 161 reasonable_max = (julong)(phys_mem / MaxRAMFraction); 162 calc_str.append(" / MaxRAMFraction"); 163 } else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) { 164 reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100); 165 calc_str.append(" * MaxRAMPercentage / 100"); 166 } else { 167 // We use our own fraction to calculate max size of young generation. 168 reasonable_max = phys_mem * MaxRamFractionForYoung; 169 calc_str.append(" * %0.2f", MaxRamFractionForYoung); 170 } 171 reasonable_max = align_up(reasonable_max, GenAlignment); 172 173 if (MaxNewSize > reasonable_max) { 174 if (FLAG_IS_CMDLINE(MaxNewSize)) { 175 log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))", 176 (size_t)reasonable_max, calc_str.buffer()); 177 } else { 178 log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). " 179 "Dram usage can be lowered by setting MaxNewSize to a lower value", (size_t)reasonable_max, calc_str.buffer()); 180 } 181 MaxNewSize = reasonable_max; 182 } 183 if (NewSize > reasonable_max) { 184 if (FLAG_IS_CMDLINE(NewSize)) { 185 log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))", 186 (size_t)reasonable_max, calc_str.buffer()); 187 } 188 NewSize = reasonable_max; 189 } 190 } 191 192 bool ParallelArguments::is_heterogeneous_heap() { 193 return AllocateOldGenAt != NULL; 194 } 195 196 size_t ParallelArguments::heap_reserved_size_bytes() { 197 if (!is_heterogeneous_heap() || !UseAdaptiveGCBoundary) { 198 return MaxHeapSize; 199 } 200 201 // Heterogeneous heap and adaptive size gc boundary 202 203 // This is the size that young gen can grow to, when UseAdaptiveGCBoundary is true. 204 size_t max_yg_size = MaxHeapSize - MinOldSize; 205 // This is the size that old gen can grow to, when UseAdaptiveGCBoundary is true. 206 size_t max_old_size = MaxHeapSize - MinNewSize; 207 208 return max_yg_size + max_old_size; 209 } 210 211 size_t ParallelArguments::heap_max_size_bytes() { 212 return MaxHeapSize; 213 } 214 215 CollectedHeap* ParallelArguments::create_heap() { 216 return new ParallelScavengeHeap(); 217 }