Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  genArguments.cpp   Sprache: C

 
/*
 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#include "precompiled.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/genArguments.hpp"
#include "gc/shared/generation.hpp"
#include "logging/log.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"

size_t MinNewSize = 0;

size_t MinOldSize = 0;
size_t MaxOldSize = 0;

size_t GenAlignment = 0;

size_t GenArguments::conservative_max_heap_alignment() { return (size_t)Generation::GenGrain; }

static size_t young_gen_size_lower_bound() {
  // The young generation must be aligned and have room for eden + two survivors
  return align_up(3 * SpaceAlignment, GenAlignment);
}

static size_t old_gen_size_lower_bound() {
  return align_up(SpaceAlignment, GenAlignment);
}

size_t GenArguments::scale_by_NewRatio_aligned(size_t base_size, size_t alignment) {
  return align_down_bounded(base_size / (NewRatio + 1), alignment);
}

static size_t bound_minus_alignment(size_t desired_size,
                                    size_t maximum_size,
                                    size_t alignment) {
  size_t max_minus = maximum_size - alignment;
  return desired_size < max_minus ? desired_size : max_minus;
}

void GenArguments::initialize_alignments() {
  // Initialize card size before initializing alignments
  CardTable::initialize_card_size();
  SpaceAlignment = GenAlignment = (size_t)Generation::GenGrain;
  HeapAlignment = compute_heap_alignment();
}

void GenArguments::initialize_heap_flags_and_sizes() {
  GCArguments::initialize_heap_flags_and_sizes();

  assert(GenAlignment != 0, "Generation alignment not set up properly");
  assert(HeapAlignment >= GenAlignment,
         "HeapAlignment: " SIZE_FORMAT " less than GenAlignment: " SIZE_FORMAT,
         HeapAlignment, GenAlignment);
  assert(GenAlignment % SpaceAlignment == 0,
         "GenAlignment: " SIZE_FORMAT " not aligned by SpaceAlignment: " SIZE_FORMAT,
         GenAlignment, SpaceAlignment);
  assert(HeapAlignment % GenAlignment == 0,
         "HeapAlignment: " SIZE_FORMAT " not aligned by GenAlignment: " SIZE_FORMAT,
         HeapAlignment, GenAlignment);

  // All generational heaps have a young gen; handle those flags here

  // Make sure the heap is large enough for two generations
  size_t smallest_new_size = young_gen_size_lower_bound();
  size_t smallest_heap_size = align_up(smallest_new_size + old_gen_size_lower_bound(),
                                       HeapAlignment);
  if (MaxHeapSize < smallest_heap_size) {
    FLAG_SET_ERGO(MaxHeapSize, smallest_heap_size);
  }
  // If needed, synchronize MinHeapSize size and InitialHeapSize
  if (MinHeapSize < smallest_heap_size) {
    FLAG_SET_ERGO(MinHeapSize, smallest_heap_size);
    if (InitialHeapSize < MinHeapSize) {
      FLAG_SET_ERGO(InitialHeapSize, smallest_heap_size);
    }
  }

  // Make sure NewSize allows an old generation to fit even if set on the command line
  if (FLAG_IS_CMDLINE(NewSize) && NewSize >= InitialHeapSize) {
    log_warning(gc, ergo)("NewSize was set larger than initial heap size, will use initial heap size.");
    FLAG_SET_ERGO(NewSize, bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment));
  }

  // Now take the actual NewSize into account. We will silently increase NewSize
  // if the user specified a smaller or unaligned value.
  size_t bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize, GenAlignment);
  bounded_new_size = MAX2(smallest_new_size, align_down(bounded_new_size, GenAlignment));
  if (bounded_new_size != NewSize) {
    FLAG_SET_ERGO(NewSize, bounded_new_size);
  }
  MinNewSize = smallest_new_size;

  if (!FLAG_IS_DEFAULT(MaxNewSize)) {
    if (MaxNewSize >= MaxHeapSize) {
      // Make sure there is room for an old generation
      size_t smaller_max_new_size = MaxHeapSize - GenAlignment;
      if (FLAG_IS_CMDLINE(MaxNewSize)) {
        log_warning(gc, ergo)("MaxNewSize (" SIZE_FORMAT "k) is equal to or greater than the entire "
                              "heap (" SIZE_FORMAT "k). A new max generation size of " SIZE_FORMAT "k will be used.",
                              MaxNewSize/K, MaxHeapSize/K, smaller_max_new_size/K);
      }
      FLAG_SET_ERGO(MaxNewSize, smaller_max_new_size);
      if (NewSize > MaxNewSize) {
        FLAG_SET_ERGO(NewSize, MaxNewSize);
      }
    } else if (MaxNewSize < NewSize) {
      FLAG_SET_ERGO(MaxNewSize, NewSize);
    } else if (!is_aligned(MaxNewSize, GenAlignment)) {
      FLAG_SET_ERGO(MaxNewSize, align_down(MaxNewSize, GenAlignment));
    }
  }

  if (NewSize > MaxNewSize) {
    // At this point this should only happen if the user specifies a large NewSize and/or
    // a small (but not too small) MaxNewSize.
    if (FLAG_IS_CMDLINE(MaxNewSize)) {
      log_warning(gc, ergo)("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
                            "A new max generation size of " SIZE_FORMAT "k will be used.",
                            NewSize/K, MaxNewSize/K, NewSize/K);
    }
    FLAG_SET_ERGO(MaxNewSize, NewSize);
  }

  if (SurvivorRatio < 1 || NewRatio < 1) {
    vm_exit_during_initialization("Invalid young gen ratio specified");
  }

  if (OldSize < old_gen_size_lower_bound()) {
    FLAG_SET_ERGO(OldSize, old_gen_size_lower_bound());
  }
  if (!is_aligned(OldSize, GenAlignment)) {
    FLAG_SET_ERGO(OldSize, align_down(OldSize, GenAlignment));
  }

  if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) {
    // NewRatio will be used later to set the young generation size so we use
    // it to calculate how big the heap should be based on the requested OldSize
    // and NewRatio.
    assert(NewRatio > 0, "NewRatio should have been set up earlier");
    size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);

    calculated_heapsize = align_up(calculated_heapsize, HeapAlignment);
    FLAG_SET_ERGO(MaxHeapSize, calculated_heapsize);
    FLAG_SET_ERGO(InitialHeapSize, calculated_heapsize);
  }

  // Adjust NewSize and OldSize or MaxHeapSize to match each other
  if (NewSize + OldSize > MaxHeapSize) {
    if (FLAG_IS_CMDLINE(MaxHeapSize)) {
      // Somebody has set a maximum heap size with the intention that we should not
      // exceed it. Adjust New/OldSize as necessary.
      size_t calculated_size = NewSize + OldSize;
      double shrink_factor = (double) MaxHeapSize / calculated_size;
      size_t smaller_new_size = align_down((size_t)(NewSize * shrink_factor), GenAlignment);
      FLAG_SET_ERGO(NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size));

      // OldSize is already aligned because above we aligned MaxHeapSize to
      // HeapAlignment, and we just made sure that NewSize is aligned to
      // GenAlignment. In initialize_flags() we verified that HeapAlignment
      // is a multiple of GenAlignment.
      FLAG_SET_ERGO(OldSize, MaxHeapSize - NewSize);
    } else {
      FLAG_SET_ERGO(MaxHeapSize, align_up(NewSize + OldSize, HeapAlignment));
    }
  }

  // Update NewSize, if possible, to avoid sizing the young gen too small when only
  // OldSize is set on the command line.
  if (FLAG_IS_CMDLINE(OldSize) && !FLAG_IS_CMDLINE(NewSize)) {
    if (OldSize < InitialHeapSize) {
      size_t new_size = InitialHeapSize - OldSize;
      if (new_size >= MinNewSize && new_size <= MaxNewSize) {
        FLAG_SET_ERGO(NewSize, new_size);
      }
    }
  }

  DEBUG_ONLY(assert_flags();)
}

// Values set on the command line win over any ergonomically
// set command line parameters.
// Ergonomic choice of parameters are done before this
// method is called.  Values for command line parameters such as NewSize
// and MaxNewSize feed those ergonomic choices into this method.
// This method makes the final generation sizings consistent with
// themselves and with overall heap sizings.
// In the absence of explicitly set command line flags, policies
// such as the use of NewRatio are used to size the generation.

// Minimum sizes of the generations may be different than
// the initial sizes.  An inconsistency is permitted here
// in the total size that can be specified explicitly by
// command line specification of OldSize and NewSize and
// also a command line specification of -Xms.  Issue a warning
// but allow the values to pass.
void GenArguments::initialize_size_info() {
  GCArguments::initialize_size_info();

  size_t max_young_size = MaxNewSize;

  // Determine maximum size of the young generation.

  if (FLAG_IS_DEFAULT(MaxNewSize)) {
    max_young_size = scale_by_NewRatio_aligned(MaxHeapSize, GenAlignment);
    // Bound the maximum size by NewSize below (since it historically
    // would have been NewSize and because the NewRatio calculation could
    // yield a size that is too small) and bound it by MaxNewSize above.
    // Ergonomics plays here by previously calculating the desired
    // NewSize and MaxNewSize.
    max_young_size = clamp(max_young_size, NewSize, MaxNewSize);
  }

  // Given the maximum young size, determine the initial and
  // minimum young sizes.
  size_t initial_young_size = NewSize;

  if (MaxHeapSize == InitialHeapSize) {
    // The maximum and initial heap sizes are the same so the generation's
    // initial size must be the same as it maximum size. Use NewSize as the
    // size if set on command line.
    max_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : max_young_size;
    initial_young_size = max_young_size;

    // Also update the minimum size if min == initial == max.
    if (MaxHeapSize == MinHeapSize) {
      MinNewSize = max_young_size;
    }
  } else {
    if (FLAG_IS_CMDLINE(NewSize)) {
      // If NewSize is set on the command line, we should use it as
      // the initial size, but make sure it is within the heap bounds.
      initial_young_size =
        MIN2(max_young_size, bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment));
      MinNewSize = bound_minus_alignment(initial_young_size, MinHeapSize, GenAlignment);
    } else {
      // For the case where NewSize is not set on the command line, use
      // NewRatio to size the initial generation size. Use the current
      // NewSize as the floor, because if NewRatio is overly large, the resulting
      // size can be too small.
      initial_young_size =
        clamp(scale_by_NewRatio_aligned(InitialHeapSize, GenAlignment), NewSize, max_young_size);
    }
  }

  log_trace(gc, heap)("1: Minimum young " SIZE_FORMAT " Initial young " SIZE_FORMAT " Maximum young " SIZE_FORMAT,
                      MinNewSize, initial_young_size, max_young_size);

  // At this point the minimum, initial and maximum sizes
  // of the overall heap and of the young generation have been determined.
  // The maximum old size can be determined from the maximum young
  // and maximum heap size since no explicit flags exist
  // for setting the old generation maximum.
  MaxOldSize = MAX2(MaxHeapSize - max_young_size, GenAlignment);

  size_t initial_old_size = OldSize;

  // If no explicit command line flag has been set for the
  // old generation size, use what is left.
  if (!FLAG_IS_CMDLINE(OldSize)) {
    // The user has not specified any value but the ergonomics
    // may have chosen a value (which may or may not be consistent
    // with the overall heap size).  In either case make
    // the minimum, maximum and initial sizes consistent
    // with the young sizes and the overall heap sizes.
    MinOldSize = GenAlignment;
    initial_old_size = clamp(InitialHeapSize - initial_young_size, MinOldSize, MaxOldSize);
    // MaxOldSize has already been made consistent above.
  } else {
    // OldSize has been explicitly set on the command line. Use it
    // for the initial size but make sure the minimum allow a young
    // generation to fit as well.
    // If the user has explicitly set an OldSize that is inconsistent
    // with other command line flags, issue a warning.
    // The generation minimums and the overall heap minimum should
    // be within one generation alignment.
    if (initial_old_size > MaxOldSize) {
      log_warning(gc, ergo)("Inconsistency between maximum heap size and maximum "
                            "generation sizes: using maximum heap = " SIZE_FORMAT
                            ", -XX:OldSize flag is being ignored",
                            MaxHeapSize);
      initial_old_size = MaxOldSize;
    }

    MinOldSize = MIN2(initial_old_size, MinHeapSize - MinNewSize);
  }

  // The initial generation sizes should match the initial heap size,
  // if not issue a warning and resize the generations. This behavior
  // differs from JDK8 where the generation sizes have higher priority
  // than the initial heap size.
  if ((initial_old_size + initial_young_size) != InitialHeapSize) {
    log_warning(gc, ergo)("Inconsistency between generation sizes and heap size, resizing "
                          "the generations to fit the heap.");

    size_t desired_young_size = InitialHeapSize - initial_old_size;
    if (InitialHeapSize < initial_old_size) {
      // Old want all memory, use minimum for young and rest for old
      initial_young_size = MinNewSize;
      initial_old_size = InitialHeapSize - MinNewSize;
    } else if (desired_young_size > max_young_size) {
      // Need to increase both young and old generation
      initial_young_size = max_young_size;
      initial_old_size = InitialHeapSize - max_young_size;
    } else if (desired_young_size < MinNewSize) {
      // Need to decrease both young and old generation
      initial_young_size = MinNewSize;
      initial_old_size = InitialHeapSize - MinNewSize;
    } else {
      // The young generation boundaries allow us to only update the
      // young generation.
      initial_young_size = desired_young_size;
    }

    log_trace(gc, heap)("2: Minimum young " SIZE_FORMAT " Initial young " SIZE_FORMAT " Maximum young " SIZE_FORMAT,
                        MinNewSize, initial_young_size, max_young_size);
  }

  // Write back to flags if necessary.
  if (NewSize != initial_young_size) {
    FLAG_SET_ERGO(NewSize, initial_young_size);
  }

  if (MaxNewSize != max_young_size) {
    FLAG_SET_ERGO(MaxNewSize, max_young_size);
  }

  if (OldSize != initial_old_size) {
    FLAG_SET_ERGO(OldSize, initial_old_size);
  }

  log_trace(gc, heap)("Minimum old " SIZE_FORMAT " Initial old " SIZE_FORMAT " Maximum old " SIZE_FORMAT,
                      MinOldSize, OldSize, MaxOldSize);

  DEBUG_ONLY(assert_size_info();)
}

#ifdef ASSERT
void GenArguments::assert_flags() {
  GCArguments::assert_flags();
  assert(NewSize >= MinNewSize, "Ergonomics decided on a too small young gen size");
  assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes");
  assert(NewSize % GenAlignment == 0, "NewSize alignment");
  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % GenAlignment == 0, "MaxNewSize alignment");
  assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes");
  assert(OldSize % GenAlignment == 0, "OldSize alignment");
}

void GenArguments::assert_size_info() {
  GCArguments::assert_size_info();
  // GenArguments::initialize_size_info may update the MaxNewSize
  assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes");
  assert(MinNewSize <= NewSize, "Ergonomics decided on incompatible minimum and initial young gen sizes");
  assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
  assert(MinNewSize % GenAlignment == 0, "_min_young_size alignment");
  assert(NewSize % GenAlignment == 0, "_initial_young_size alignment");
  assert(MaxNewSize % GenAlignment == 0, "MaxNewSize alignment");
  assert(MinNewSize <= bound_minus_alignment(MinNewSize, MinHeapSize, GenAlignment),
      "Ergonomics made minimum young generation larger than minimum heap");
  assert(NewSize <=  bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment),
      "Ergonomics made initial young generation larger than initial heap");
  assert(MaxNewSize <= bound_minus_alignment(MaxNewSize, MaxHeapSize, GenAlignment),
      "Ergonomics made maximum young generation lager than maximum heap");
  assert(MinOldSize <= OldSize, "Ergonomics decided on incompatible minimum and initial old gen sizes");
  assert(OldSize <= MaxOldSize, "Ergonomics decided on incompatible initial and maximum old gen sizes");
  assert(MaxOldSize % GenAlignment == 0, "MaxOldSize alignment");
  assert(OldSize % GenAlignment == 0, "OldSize alignment");
  assert(MaxHeapSize <= (MaxNewSize + MaxOldSize), "Total maximum heap sizes must be sum of generation maximum sizes");
  assert(MinNewSize + MinOldSize <= MinHeapSize, "Minimum generation sizes exceed minimum heap size");
  assert(NewSize + OldSize == InitialHeapSize, "Initial generation sizes should match initial heap size");
  assert(MaxNewSize + MaxOldSize == MaxHeapSize, "Maximum generation sizes should match maximum heap size");
}
#endif // ASSERT

97%


¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge