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