1 /*
   2  * Copyright (c) 2018, 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 
  39 static const double MaxRamFractionForYoung = 0.8;
  40 
  41 size_t ParallelArguments::conservative_max_heap_alignment() {
  42   return compute_heap_alignment();
  43 }
  44 
  45 void ParallelArguments::initialize() {
  46   GCArguments::initialize();
  47   assert(UseParallelGC || UseParallelOldGC, "Error");
  48   // Enable ParallelOld unless it was explicitly disabled (cmd line or rc file).
  49   if (FLAG_IS_DEFAULT(UseParallelOldGC)) {
  50     FLAG_SET_DEFAULT(UseParallelOldGC, true);
  51   }
  52   FLAG_SET_DEFAULT(UseParallelGC, true);
  53 
  54   // If no heap maximum was requested explicitly, use some reasonable fraction
  55   // of the physical memory, up to a maximum of 1GB.
  56   FLAG_SET_DEFAULT(ParallelGCThreads,
  57                    WorkerPolicy::parallel_worker_threads());
  58   if (ParallelGCThreads == 0) {
  59     jio_fprintf(defaultStream::error_stream(),
  60         "The Parallel GC can not be combined with -XX:ParallelGCThreads=0\n");
  61     vm_exit(1);
  62   }
  63 
  64   if (UseAdaptiveSizePolicy) {
  65     // We don't want to limit adaptive heap sizing's freedom to adjust the heap
  66     // unless the user actually sets these flags.
  67     if (FLAG_IS_DEFAULT(MinHeapFreeRatio)) {
  68       FLAG_SET_DEFAULT(MinHeapFreeRatio, 0);
  69     }
  70     if (FLAG_IS_DEFAULT(MaxHeapFreeRatio)) {
  71       FLAG_SET_DEFAULT(MaxHeapFreeRatio, 100);
  72     }
  73   }
  74 
  75   // If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the
  76   // SurvivorRatio has been set, reset their default values to SurvivorRatio +
  77   // 2.  By doing this we make SurvivorRatio also work for Parallel Scavenger.
  78   // See CR 6362902 for details.
  79   if (!FLAG_IS_DEFAULT(SurvivorRatio)) {
  80     if (FLAG_IS_DEFAULT(InitialSurvivorRatio)) {
  81        FLAG_SET_DEFAULT(InitialSurvivorRatio, SurvivorRatio + 2);
  82     }
  83     if (FLAG_IS_DEFAULT(MinSurvivorRatio)) {
  84       FLAG_SET_DEFAULT(MinSurvivorRatio, SurvivorRatio + 2);
  85     }
  86   }
  87 
  88   if (UseParallelOldGC) {
  89     // Par compact uses lower default values since they are treated as
  90     // minimums.  These are different defaults because of the different
  91     // interpretation and are not ergonomically set.
  92     if (FLAG_IS_DEFAULT(MarkSweepDeadRatio)) {
  93       FLAG_SET_DEFAULT(MarkSweepDeadRatio, 1);
  94     }
  95   }
  96 }
  97 
  98 // The alignment used for boundary between young gen and old gen
  99 static size_t default_gen_alignment() {
 100   return 64 * K * HeapWordSize;
 101 }
 102 
 103 void ParallelArguments::initialize_alignments() {
 104   SpaceAlignment = GenAlignment = default_gen_alignment();
 105   HeapAlignment = compute_heap_alignment();
 106 }
 107 
 108 void ParallelArguments::initialize_heap_flags_and_sizes_one_pass() {
 109   // Do basic sizing work
 110   GenArguments::initialize_heap_flags_and_sizes();
 111 
 112   // The survivor ratio's are calculated "raw", unlike the
 113   // default gc, which adds 2 to the ratio value. We need to
 114   // make sure the values are valid before using them.
 115   if (MinSurvivorRatio < 3) {
 116     FLAG_SET_ERGO(MinSurvivorRatio, 3);
 117   }
 118 
 119   if (InitialSurvivorRatio < 3) {
 120     FLAG_SET_ERGO(InitialSurvivorRatio, 3);
 121   }
 122 }
 123 
 124 void ParallelArguments::initialize_heap_flags_and_sizes() {
 125   if (is_heterogeneous_heap()) {
 126     initialize_heterogeneous();
 127   }
 128 
 129   initialize_heap_flags_and_sizes_one_pass();
 130 
 131   const size_t max_page_sz = os::page_size_for_region_aligned(MaxHeapSize, 8);
 132   const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
 133   const size_t min_page_sz = os::page_size_for_region_aligned(MinHeapSize, min_pages);
 134   const size_t page_sz = MIN2(max_page_sz, min_page_sz);
 135 
 136   // Can a page size be something else than a power of two?
 137   assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
 138   size_t new_alignment = align_up(page_sz, GenAlignment);
 139   if (new_alignment != GenAlignment) {
 140     GenAlignment = new_alignment;
 141     SpaceAlignment = new_alignment;
 142     // Redo everything from the start
 143     initialize_heap_flags_and_sizes_one_pass();
 144   }
 145 }
 146 
 147 // Check the available dram memory to limit NewSize and MaxNewSize before
 148 // calling base class initialize_flags().
 149 void ParallelArguments::initialize_heterogeneous() {
 150   FormatBuffer<100> calc_str("");
 151 
 152   julong phys_mem;
 153   // If MaxRam is specified, we use that as maximum physical memory available.
 154   if (FLAG_IS_DEFAULT(MaxRAM)) {
 155     phys_mem = os::physical_memory();
 156     calc_str.append("Physical_Memory");
 157   } else {
 158     phys_mem = (julong)MaxRAM;
 159     calc_str.append("MaxRAM");
 160   }
 161 
 162   julong reasonable_max = phys_mem;
 163 
 164   // If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
 165   // reasonable max size of young generation.
 166   if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
 167     reasonable_max = (julong)(phys_mem / MaxRAMFraction);
 168     calc_str.append(" / MaxRAMFraction");
 169   } else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
 170     reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
 171     calc_str.append(" * MaxRAMPercentage / 100");
 172   } else {
 173     // We use our own fraction to calculate max size of young generation.
 174     reasonable_max = phys_mem * MaxRamFractionForYoung;
 175     calc_str.append(" * %0.2f", MaxRamFractionForYoung);
 176   }
 177   reasonable_max = align_up(reasonable_max, GenAlignment);
 178 
 179   if (MaxNewSize > reasonable_max) {
 180     if (FLAG_IS_CMDLINE(MaxNewSize)) {
 181       log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
 182                             (size_t)reasonable_max, calc_str.buffer());
 183     } else {
 184       log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
 185                          "Dram usage can be lowered by setting MaxNewSize to a lower value", (size_t)reasonable_max, calc_str.buffer());
 186     }
 187     MaxNewSize = reasonable_max;
 188   }
 189   if (NewSize > reasonable_max) {
 190     if (FLAG_IS_CMDLINE(NewSize)) {
 191       log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
 192                             (size_t)reasonable_max, calc_str.buffer());
 193     }
 194     NewSize = reasonable_max;
 195   }
 196 }
 197 
 198 bool ParallelArguments::is_heterogeneous_heap() {
 199   return AllocateOldGenAt != NULL;
 200 }
 201 
 202 size_t ParallelArguments::heap_reserved_size_bytes() {
 203   if (!is_heterogeneous_heap() || !UseAdaptiveGCBoundary) {
 204     return MaxHeapSize;
 205   }
 206 
 207   // Heterogeneous heap and adaptive size gc boundary
 208 
 209   // This is the size that young gen can grow to, when UseAdaptiveGCBoundary is true.
 210   size_t max_yg_size = MaxHeapSize - MinOldSize;
 211   // This is the size that old gen can grow to, when UseAdaptiveGCBoundary is true.
 212   size_t max_old_size = MaxHeapSize - MinNewSize;
 213 
 214   return max_yg_size + max_old_size;
 215 }
 216 
 217 CollectedHeap* ParallelArguments::create_heap() {
 218   return new ParallelScavengeHeap();
 219 }