[JAVA] Standardwerte für MaxHeapSize und InitialHeapSize

Einführung

Die Standardwerte für MaxHeapSize (-Xmx) und InitialHeapSize sind in der offiziellen Dokumentation etwas geschrieben, aber nicht detailliert. Also habe ich es zusammen mit der Quelle nachgeschlagen.

Zielversion ist OpenJDK 11 Die tatsächliche Maschinenbestätigungsumgebung ist CentOS7

Fazit

MaxHeapSize MaxHeapSize wird wie folgt bestimmt.

Speichergröße(※1) Wert
Über 248M oder weniger(※2) Speichergröße* 0.5 (※4)
Ungefähr 248 M bis 496 M oder weniger MaxHeapSize(124MB)
Ungefähr 496 M bis 120 G oder weniger(※3) Speichergröße* 0.25 (※5)
Über 120G oder mehr Über 30G(※6)

Mehr Details.

(※1) Wenn MaxRAM angegeben ist, dessen Wert, andernfalls die tatsächliche Speichergröße. Von nun an wird die Speichergröße in diesem Sinne verwendet.

(※2) 248M ist aus dem Folgenden. MaxHeapSize / (MinRAMPercentage/100) = 124M / (50/100) = 248M

(※4) 0,5 ist der Wert von MinRAM Percentage, genau genommen: Speichergröße * (MinRAMPercentage / 100)

(※5) Genau genommen ist 0,25 der MaxRAM-Prozentwert: Speichergröße * (MaxRAMPercentage / 100)

(※6) 30 GB sind aus dem Folgenden. 32GB - HeapBaseMinAddress (=2GB) 32 GB ist der maximale Java-Heap-Offset bei Verwendung von Compressed Oops. Details werden in der Quelle erklärt.

InitialHeapSize Der Standardwert von InitialHeapSize wird wie folgt bestimmt. Welche der folgenden Optionen größer ist (jedoch MaxHeapSize nicht überschreitet)

Quelle

Anfänglicher Standardwert für MaxHeapSize

Der erste Standardwert für MaxHeapSize ist unten definiert. Src / Hotspot wird im folgenden Quellpfad weggelassen.

share/gc/shared/gc_globals.hpp



  product(size_t, MaxHeapSize, ScaleForWordSize(96*M),                      \
          "Maximum heap size (in bytes)")                                   \
          constraint(MaxHeapSizeConstraintFunc,AfterErgo)                   \

ScaleForWordSize ist unten definiert.

share/runtime/globals.hpp


#ifdef _LP64
#define ScaleForWordSize(x) align_down_((x) * 13 / 10, HeapWordSize)
#else
#define ScaleForWordSize(x) (x)
#endif

Daher beträgt MaxHeapSize 96 * 1,3 = 124,8 MB 1.3 scheint die Tatsache zu berücksichtigen, dass die Zeigergröße im Vergleich zu 32 Bit verdoppelt ist.

set_heap_size()

MaxHeapSize Der Standardwert von InitialHeapSize wird hauptsächlich durch set_heap_size () in arguments.cpp bestimmt.

share/runtime/arguments.cpp


void Arguments::set_heap_size() {
  julong phys_mem =
    FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM)
                            : (julong)MaxRAM;

Wenn MaxRAM angegeben ist, MaxRAM Sofern nicht anders angegeben, wird MaxRAM (Standard 1G) oder der kleinere physische Speicher auf phys_mem festgelegt.

set_heap_size()


  // Convert deprecated flags
  if (FLAG_IS_DEFAULT(MaxRAMPercentage) &&
      !FLAG_IS_DEFAULT(MaxRAMFraction))
    MaxRAMPercentage = 100.0 / MaxRAMFraction;

  if (FLAG_IS_DEFAULT(MinRAMPercentage) &&
      !FLAG_IS_DEFAULT(MinRAMFraction))
    MinRAMPercentage = 100.0 / MinRAMFraction;

  if (FLAG_IS_DEFAULT(InitialRAMPercentage) &&
      !FLAG_IS_DEFAULT(InitialRAMFraction))
    InitialRAMPercentage = 100.0 / InitialRAMFraction;

MaxRAMFraction MinRAMFraction InitialRAMFraction ist jetzt veraltet und wird durch MaxRAMPercentage MinRAMPercentage InitialRAMFraction ersetzt. Wenn in der alten Option angegeben, konvertieren Sie hier in die neue Option. In der Vergangenheit wurde es als Bruchteil des Speichers angegeben, in Java 11 jedoch als Prozentsatz des Speichers.

set_heap_size()


  // If the maximum heap size has not been set with -Xmx,
  // then set it as fraction of the size of physical memory,
  // respecting the maximum and minimum sizes of the heap.
  if (FLAG_IS_DEFAULT(MaxHeapSize)) {
    julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
    const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100);
    if (reasonable_min < MaxHeapSize) {
      // Small physical memory, so use a minimum fraction of it for the heap
      reasonable_max = reasonable_min;
    } else {
      // Not-small physical memory, so require a heap at least
      // as large as MaxHeapSize
      reasonable_max = MAX2(reasonable_max, (julong)MaxHeapSize);
    }

Wenn MaxHeapSize nicht angegeben ist und der Speicher 248 MB (MaxHeapSize / (MinRAMPercentage / 100)) oder weniger beträgt angemessen_max = Speicher * 0,5 Andernfalls angemessen_max = Speicher * 0,25 oder 126M größer Wird sein. angemessen_max ist der Wert, der später (wobei ★) als MaxHeapSize festgelegt wird.

set_heap_size()


    if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
      // Limit the heap size to ErgoHeapSizeLimit
      reasonable_max = MIN2(reasonable_max, (julong)ErgoHeapSizeLimit);
    }

ErgoHeapSizeLimit ist standardmäßig 0 Wenn ErgoHeapSizeLimit angegeben ist und kleiner als angemessen_max ist, setzen Sie angemessen_max auf ErgoHeapSizeLimit. Die Verwendung von ErgoHeapSizeLimit ist unbekannt. Wird nur hier verwendet.

set_heap_size()


    if (UseCompressedOops) {
      // Limit the heap size to the maximum possible when using compressed oops
      julong max_coop_heap = (julong)max_heap_for_compressed_oops();  // 32GB

      // HeapBaseMinAddress can be greater than default but not less than.
      if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {  // HeapBaseMinAddress = 2GB
        if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) {
          // matches compressed oops printing flags
          log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least " SIZE_FORMAT
                                     " (" SIZE_FORMAT "G) which is greater than value given " SIZE_FORMAT,
                                     DefaultHeapBaseMinAddress,
                                     DefaultHeapBaseMinAddress/G,
                                     HeapBaseMinAddress);
          FLAG_SET_ERGO(size_t, HeapBaseMinAddress, DefaultHeapBaseMinAddress);
        }
      }

      if (HeapBaseMinAddress + MaxHeapSize < max_coop_heap) { // 2G + 124M < 32G
        // Heap should be above HeapBaseMinAddress to get zero based compressed oops
        // but it should be not less than default MaxHeapSize.
        max_coop_heap -= HeapBaseMinAddress;  //Über 30 GB
      }
      reasonable_max = MIN2(reasonable_max, max_coop_heap);
    }

CompressedOop-Verarbeitung. UseCompressedOops ist unter 64-Bit-Betriebssystemen standardmäßig wahr. max_heap_for_compressed_oops () gibt den maximalen Java-Heap-Offset (= 32 GB) in CompressedOop zurück. (Details werden später beschrieben) Wenn HeapBaseMinAddress kleiner als der Standardwert von 2 GB ist, wird dies auf 2 GB korrigiert. Wenn HeapBaseMinAddress + MaxHeapSize weniger als 32 GB beträgt (standardmäßig true) Setzen Sie angemessen_max auf 32 GB --HeapBaseMinAddress (= 30 GB). Dies liegt daran, dass die Java-Heap-Größe um die Java-Heap-Startadresse (HeapBaseMinAddress) reduziert werden muss.

set_heap_size()


    reasonable_max = limit_by_allocatable_memory(reasonable_max);

Überprüfen Sie, ob eine Zuordnung mit der im vorherigen Prozess ermittelten Größe von angemessen_max möglich ist, und legen Sie, falls nicht, die mögliche Größe fest.

set_heap_size()


    if (!FLAG_IS_DEFAULT(InitialHeapSize)) {  //InitialHeapSize Standard 0
      // An initial heap size was specified on the command line,
      // so be sure that the maximum size is consistent.  Done
      // after call to limit_by_allocatable_memory because that
      // method might reduce the allocation size.
      reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize);
    }

Wenn InitialHeapSize festgelegt ist, wird angemessenes_max auf den größeren Wert von angemessenem_max und InitialHeapSize festgelegt. Es ist inkonsistent, dass MaxHeapSize kleiner als InitialHeapSize ist.

set_heap_size()


    log_trace(gc, heap)("  Maximum heap size " SIZE_FORMAT, (size_t) reasonable_max);
    FLAG_SET_ERGO(size_t, MaxHeapSize, (size_t)reasonable_max);
  }

Setzen Sie vernünftige_max, die im vorherigen Prozess ermittelt wurde, als MaxHeapSize. (★)

set_heap_size()


  // If the minimum or initial heap_size have not been set or requested to be set
  // ergonomically, set them accordingly.

  if (InitialHeapSize == 0 || min_heap_size() == 0) {
    julong reasonable_minimum = (julong)(OldSize + NewSize);

    reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize);

    reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum);

    if (InitialHeapSize == 0) {
      julong reasonable_initial = (julong)((phys_mem * InitialRAMPercentage) / 100);

      reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, (julong)min_heap_size());
      reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);

      reasonable_initial = limit_by_allocatable_memory(reasonable_initial);

      log_trace(gc, heap)("  Initial heap size " SIZE_FORMAT, (size_t)reasonable_initial);
      FLAG_SET_ERGO(size_t, InitialHeapSize, (size_t)reasonable_initial);
    }
    ....

Wenn InitialHeapSize nicht festgelegt ist, ist InitialHeapSize

max_heap_for_compressed_oops()

max_heap_for_compressed_oops gibt 32 GB zurück. Dies ist der maximale Java-Heap-Offset in Compressed Oop.

python


size_t Arguments::max_heap_for_compressed_oops() {
  // Avoid sign flip.
  assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size");
  // We need to fit both the NULL page and the heap into the memory budget, while
  // keeping alignment constraints of the heap. To guarantee the latter, as the
  // NULL page is located before the heap, we pad the NULL page to the conservative
  // maximum alignment that the GC may ever impose upon the heap.

  size_t displacement_due_to_null_page = align_up((size_t)os::vm_page_size(),
                                                  _conservative_max_heap_alignment);

  LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page);
  NOT_LP64(ShouldNotReachHere(); return 0);
}

Displacement_due_to_null_page ist 4K. OopEncodingHeapMax ist unten festgelegt.

python


void set_object_alignment() {
  ....

  LogMinObjAlignmentInBytes  = exact_log2(ObjectAlignmentInBytes);
  LogMinObjAlignment         = LogMinObjAlignmentInBytes - LogHeapWordSize;

  // Oop encoding heap max
  OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;

LogMinObjAlignmentInBytes ist wie folgt 8.

share/runtime/globals.hpp


  lp64_product(intx, ObjectAlignmentInBytes, 8,                             \
          "Default object alignment in bytes, 8 is minimum")                \

LogMinObjAlignmentInBytes ist also 3 in log2 (8) OopEncodingHeapMax ist 0x1 0000 0000 = 4 GB << 3 und 32 GB

HeapBaseMinAddress ist 2 GB

os_cpu/linux_x86/globals_linux_x86.hpp


// Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(size_t, HeapBaseMinAddress,     2*G);

Daher ist max_coop_heap = 32 GB - 2 GB = ungefähr 30 GB (tatsächlich ist es ein wenig anders, weil es Ausrichtung usw. gibt).

Tatsächliche Maschinenbestätigung

Ich habe den obigen Inhalt mit PrintFlagsInitial oder PrintFlagsFinal auf dem tatsächlichen Computer bestätigt. Das Ausgabeergebnis wird entsprechend weggelassen. Als Speichergröße wird MaxRAM verwendet.

MaxHeapSize Anfänglicher Standardwert für MaxHeapSize (mit PrintFlagsInitial) centos7 >> java -XX:+PrintFlagsInitial -version | grep MaxHeapSize size_t MaxHeapSize = 130862280

Wenn die Speichergröße 1024 m beträgt, beträgt sie 256 m, was 1/4 davon entspricht. centos7 >> java -XX:MaxRAM=1024m -XX:+PrintFlagsFinal -version | grep MaxHeapSize size_t MaxHeapSize = 268435456

Wenn die Speichergröße 248 m beträgt, ist sie mit 124 m halb so groß. centos7 >> java -XX:MaxRAM=248m -XX:+PrintFlagsFinal -version | grep MaxHeapSize size_t MaxHeapSize = 130023424

Wenn die Speichergröße 120 G beträgt, beträgt sie ungefähr 30 G (29,97 G). centos7 >> java -XX:MaxRAM=120G -XX:+PrintFlagsFinal -version | grep MaxHeapSize size_t MaxHeapSize = 32178700288

Wenn MaxRAMPercentage 10 ist, beträgt es 10% der Speichergröße 10G. centos7 >> java -XX:MaxRAM=10G -XX:MaxRAMPercentage=10 -XX:+PrintFlagsFinal -version | grep MaxHeapSize size_t MaxHeapSize = 1073741824

InitialHeapSize InitialHeapSize ist standardmäßig 1 MB groß, was 1/64 der Speichergröße entspricht. centos7 >> java -XX:MaxRAM=640M -XX:+PrintFlagsFinal -version | grep InitialHeapSize size_t InitialHeapSize = 10485760

Wenn InitialRAMPercentage 5 ist, beträgt es 5% der Speichergröße 10G. centos7 >> java -XX:MaxRAM=10G -XX:InitialRAMPercentage=5 -XX:+PrintFlagsFinal -version | grep InitialHeapSize size_t InitialHeapSize = 536870912

Wenn die Summe aus OldSize und NewSize größer als der Standardwert von InitialHeapSize ist, beträgt der Wert 40M. centos7 >> java -XX:MaxRAM=640M -XX:OldSize=20m -XX:NewSize=20m -XX:+PrintFlagsFinal -version | grep InitialHeapSize size_t InitialHeapSize = 41943040

Recommended Posts

Standardwerte für MaxHeapSize und InitialHeapSize
[Ruby] Schlüsselwörter mit Schlüsselwörtern und Standardwerten von Argumenten
Standardwert für server.servlet.session.timeout
Mit Java8 LocalDateTime und Java6 Date ist es schwierig, Mindestwerte zu verarbeiten
Über für Anweisung und wenn Anweisung
Standardwert von Android: exportiert
RxAndroid und RxSwing Scheduler
Java während und für Anweisungen