2015-09-30 4 views
9

Und in der Regel sind die Einheiten für den -Xmx, -Xms und -Xmn Optionen verwendet ("k", "M" und "G", oder die weniger Standard-Möglichkeiten "K", "m" oder "g") Binary prefix Multiples (dh Potenzen von 1024), oder sind sie 1000?Bedeutet Java-Xmx1G 10^9 oder 2^30 Bytes?

Die Handbücher sagen, dass sie Kilobyte (KB), Megabyte (MB) und Gigabyte (GB) darstellen, was darauf hindeutet, dass sie Potenzen von 1000 sind, wie im ursprünglichen SI System definiert. Meine informellen Tests (denen ich nicht sehr sicher bin) deuten darauf hin, dass sie wirklich kibibytes (kiB), mebibytes (MiB) und gibibytes (GiB) sind, alle Leistungen von 1024.

Also was ist richtig? Z.B. Welcher Java-Code würde die aktuelle Größe anzeigen?

Die Verwendung von Vielfachen von 1024 ist für RAM-Größen nicht überraschend, da RAM normalerweise durch das Verdoppeln von Hardwaremodulen ausgelegt wird. Die Verwendung von Einheiten in einer klaren und standardisierten Weise ist jedoch immer wichtiger, da wir zu immer größeren Mächten gelangen, da das Potenzial für Verwirrung wächst. Die Einheit "t" wird auch von meiner JVM akzeptiert und 1 TiB ist 10% größer als 1 TB.

Hinweis: Wenn diese wirklich binäre Vielfache sind, schlage ich vor, die Dokumentation und Benutzeroberflächen Aktualisierung darüber sehr klar sein, mit Beispielen wie "Fügen Sie die Buchstaben k oder K, um anzuzeigen, kibibytes (1024 Byte) oder m oder M zur Angabe von Mebibyten (1048576 Bytes) ". Das ist der Ansatz, der beispielsweise in Ubuntu genommen wurde: UnitsPolicy - Ubuntu Wiki.

Hinweis: Weitere Informationen zu den Optionen finden Sie unter z. java - What are the Xms and Xmx parameters when starting JVMs?.

+0

@ElliottFrisch Hauptsächlich stelle ich die Frage, auf der Suche nach einer endgültigen Antwort. Der Dokumentationsvorschlag soll nur mehr Klarheit darüber geben, worüber ich verwirrt bin. – nealmcb

Antwort

17

Kurze Antwort: Alle Speichergrößen durch die JVM-Befehlszeilenargumente verwendet werden, in den traditionellen binären Einheiten angegeben, wobei ein Kilobyte 1024 Bytes ist, und die anderen Kräfte von 1024 zu erhöhen.

Lange Antwort:

This documentation page on the command line arguments sagt der folgende auf alle Argumente gilt die Annahme Speichergrößen:

Zum Beispiel die Größe auf 8 GB einzustellen, können Sie entweder 8g angeben, 8192m, 8388608k oder 8589934592 als Argument.

Für -Xmx, gibt es diese spezifischen Beispiele:

Die folgenden Beispiele zeigen, wie die maximal zulässige Größe des zugewiesenen Speichers auf 80 MB mit verschiedenen Einheiten:

-Xmx83886080
-Xmx81920k
-Xmx80m

Bevor ich überlegte, die Dokumentation zu überprüfen (ich nahm an, dass Sie bereits hatten?), Überprüfte ich die Quelle von HotSpot und fand die Speicherwerte in src/share/vm/runtime/arguments.cpp durch die Funktion atomull (die für "ASCII to memory, unsigned" zu stehen scheint long long "):

// Parses a memory size specification string. 
static bool atomull(const char *s, julong* result) { 
    julong n = 0; 
    int args_read = sscanf(s, JULONG_FORMAT, &n); 
    if (args_read != 1) { 
    return false; 
    } 
    while (*s != '\0' && isdigit(*s)) { 
    s++; 
    } 
    // 4705540: illegal if more characters are found after the first non-digit 
    if (strlen(s) > 1) { 
    return false; 
    } 
    switch (*s) { 
    case 'T': case 't': 
     *result = n * G * K; 
     // Check for overflow. 
     if (*result/((julong)G * K) != n) return false; 
     return true; 
    case 'G': case 'g': 
     *result = n * G; 
     if (*result/G != n) return false; 
     return true; 
    case 'M': case 'm': 
     *result = n * M; 
     if (*result/M != n) return false; 
     return true; 
    case 'K': case 'k': 
     *result = n * K; 
     if (*result/K != n) return false; 
     return true; 
    case '\0': 
     *result = n; 
     return true; 
    default: 
     return false; 
    } 
} 

diese Konstanten K, M, G in src/share/vm/utilities/globalDefinitions.hpp definiert sind:

const size_t K     = 1024; 
const size_t M     = K*K; 
const size_t G     = M*K; 

All dies bestätigt die Dokumentation, mit der Ausnahme, dass Unterstützung für das T Suffix für Terabyte wurde offenbar später hinzugefügt und ist überhaupt nicht dokumentiert.

Es ist nicht zwingend eine Einheit Multiplikator zu verwenden, wenn Sie also eine Milliarde Bytes wollen Sie können -Xmx1000000000 schreiben. Wenn Sie einen Multiplikator verwenden, sind sie binär, also -Xmx1G bedeutet 2 Bytes, oder ein Stick o 'RAM. Das ist nicht wirklich überraschend, da Java dem Versuch der IEC vorausgeht, existierende Wörter rückwirkend neu zu definieren. Eine Verwechslung hätte möglich sein können, wenn die IEC lediglich die Unterscheidung der Speichereinheiten mit den Qualifizierern "binär" und "dezimal" empfohlen hätte gelegentlich mal war ihre Bedeutung nicht klar. ZB binärer Gigabyte (GB) = 1024 Bytes und dezimal Gigabyte (GB) = 1000 Bytes. Aber nein, sie definierte die Worte neu, die jeder bereits benutzte, was unweigerlich zu Verwirrung und Leavi führte Wir hielten uns an diese Clownbegriffe "gibibyte", "tebibyte" und den Rest. Oh Gott, verschone uns.)

+2

Vielen Dank für das Finden des Codes ! Sehr deutlich. Aber ich muss beachten, dass es die Computerleute sind, die zuvor eindeutige Begriffe neu definiert haben, die über zwei Jahrhunderte alt waren. Dass die IEC sie so hält, wie sie schon so lange benutzt wurden und neue Begriffe für neue Einheiten liefern, macht für mich allen Sinn. MiB ist viel weniger umständlich und viel einfacher formatiert, übersetzt usw. als "binary megabyte" oder "MB_2". – nealmcb

+0

Vielen Dank, dass Sie diese Dokumentation gefunden haben. Es hat viel klarere Beispiele, um ihre Verwendung von MB und GB zu verdeutlichen, als die Dokumentation, die ich auf meinem System (Ubuntu) und in meinen Websuchen gefunden hatte. Sieht so aus, als hätten sie es geklärt, vielleicht für Java 8 :) – nealmcb

2

Sie haben zwei Möglichkeiten Antwort auf Ihre Frage zu erhalten:

a) Quellcode von JDK überprüfen. Leider konnte ich in 5 Minuten nicht googeln.

b) schreiben Sie eine Simulation, führen Sie sie mehrmals aus und machen Sie einige Beobachtungen.

public class A { 
    public static void main(String[] args) throws Exception { 
    System.out.println("total: " + Runtime.getRuntime().totalMemory()); 
    } 
} 

und führen Sie es mehrmals:

java -Xms130m -Xmx2G A 
total: 131072000 
java -Xms131m -Xmx2G A 
total: 132644864 
java -Xms132m -Xmx2G A 
total: 132644864 
java -Xms133m -Xmx2G A 
total: 134742016 
java -Xms134m -Xmx2G A 
total: 134742016 

So Vermutung ist, dass Java nicht eine genaue Zahl verwendet, aber 2^n Annäherung der Zahl, die Sie angefordert.

1

In einem weiteren question bezüglich des -Xmx Flags wird Runtime.getRuntime().maxMemory() verwendet, um die aktuelle Größe anzuzeigen. Es wird auch angemerkt, dass -Xmx1024m und -Xmx1g zu einer identischen Ausgabe führen, was anzeigt, dass die Zahlen Potenzen von zwei statt zehn sind.

Beachten Sie auch den Unterschied zwischen totalMemory() und maxMemory().
What are Runtime.getRuntime().totalMemory() and freeMemory()?

+0

Die Frage, auf die Sie verweisen, ist genau richtig! Schauen Sie sich insbesondere [Klasse MemTest von Alex] an (http: // stackoverflow.com/a/23702224/507544) dort für eine vollständige Buchhaltung von Nicht-Heap-Speicher (einschließlich Code-Cache und Perm gen Pools) vs Heap-Speicher (einschließlich Eden Space, Survivor Raum und Tenured gen Pools) – nealmcb