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 }