2015-09-30 18 views
9

E in generale, sono le unità utilizzate per le opzioni -Xmx,e -Xmn ("k", "M" e "G", o le meno possibilità standard "K", "m" o "g") Binary prefix multipli (cioè poteri di 1024), o sono poteri di 1000?java -Xmx1G significa 10^9 o 2^30 byte?

I manuali indicano che rappresentano kilobyte (kB), megabyte (MB) e gigabyte (GB), suggerendo che sono potenze di 1000 come definito nel sistema originale SI. I miei test informali (di cui non sono molto fiducioso) suggeriscono che sono in realtà kibibytes (kiB), mebibytes (MiB) e gibibytes (GiB), tutti i poteri di 1024.

Quindi quale è giusto? Per esempio. quale codice Java mostrerebbe la dimensione corrente?

L'utilizzo di multipli di 1024 non è sorprendente per le dimensioni della RAM, poiché la RAM è in genere strutturata fisicamente raddoppiando i moduli hardware. Ma usare le unità in modo chiaro e standard è sempre più importante quando arriviamo a poteri sempre più grandi, dal momento che il potenziale di confusione aumenta. L'unità "t" è accettata anche dalla mia JVM, e 1 TiB è il 10% più grande di 1 TB.

Nota: se questi sono realmente multipli binari, suggerisco di aggiornare la documentazione e le interfacce utente per essere molto chiari su questo, con esempi come "Aggiungere la lettera k o K per indicare i kibibyte (1024 byte) o m oppure M per indicare i mebibyte (1048576 byte) ". Questo è l'approccio adottato, ad es. In Ubuntu: UnitsPolicy - Ubuntu Wiki.

Nota: per ulteriori informazioni sulle opzioni utilizzate, vedere ad es. java - What are the Xms and Xmx parameters when starting JVMs?.

+0

@ElliottFrisch Principalmente sto facendo la domanda, cercando una risposta definitiva. Il suggerimento della documentazione è inteso solo per aggiungere più chiarezza su ciò di cui sono confuso. – nealmcb

risposta

17

Risposta breve: Tutti i formati di memoria utilizzati dagli argomenti della riga di comando JVM sono specificati nelle unità tradizionali binari, dove un kilobyte è 1024 byte, e gli altri sono potenze di 1024 in aumento.

Risposta lunga:

This documentation page on the command line arguments dice il seguente si applica a tutti gli argomenti che accettano dimensioni di memoria:

Ad esempio, per impostare la dimensione a 8 GB, è possibile specificare 8g, 8192m, 8388608k o 8589934592 come argomento.

Per -Xmx, dà questi esempi specifici:

I seguenti esempi mostrano come impostare la dimensione massima consentita di memoria allocata a 80 MB utilizzando diverse unità:

-Xmx83886080
-Xmx81920k
-Xmx80m

Prima che pensassi di controllare la documentazione (ho pensato che tu avessi già?), Ho controllato la fonte di HotSpot e ho trovato i valori della memoria analizzati in src/share/vm/runtime/arguments.cpp dalla funzione atomull (che sembra indicare "ASCII in memoria, non firmato 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; 
    } 
} 

queste costanti K, M, G sono definiti in src/share/vm/utilities/globalDefinitions.hpp:

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

Tutto questo conferma la documentazione, ad eccezione che il sostegno il suffisso T per terabyte è stato apparentemente aggiunto in seguito e non è affatto documentato.

Non è obbligatorio utilizzare un moltiplicatore di unità, quindi se si desidera un miliardo di byte è possibile scrivere -Xmx1000000000. Se si utilizza un moltiplicatore, sono binari, quindi -Xmx1G significa 2 byte o uno stick o 'RAM.

(che non è davvero sorprendente, perché Java precede il tentativo del CEI per ridefinire retroattivamente parole esistenti. La confusione avrebbe potuto essere salvato se la norma IEC aveva semplicemente consigliato disambiguare le unità di memoria con le qualificazioni "binario" e "decimali" la volte occasionali loro significato non era chiaro. Ad esempio, gigabyte (GB binari) = 1024 byte e gigabyte (GB decimali) = 1000 byte. Ma no, ridefinito le parole che tutti già usavano, inevitabilmente facendo esplodere la confusione e il leavi ci siamo bloccati con questi termini da clown "gibibyte", "tebibyte" e il resto. Oh Dio ci risparmi.)

+2

Grazie per aver trovato il codice ! Molto chiaro. Ma devo notare che sono le persone del computer che hanno ridefinito termini precedentemente non ambigui che risalivano a più di due secoli fa. Perché l'IEC mantenerli così come erano stati usati per così tanto tempo, e fornire nuovi termini per nuove unità, mi ha dato ogni sorta di senso. Il MiB è molto meno ingombrante e molto più facilmente formattato, tradotto ecc. Di "binary megabyte" o "MB_2". – nealmcb

+0

Grazie per aver trovato quella documentazione. Ha esempi molto più chiari per chiarire il loro uso di MB e GB rispetto alla documentazione che ho trovato sul mio sistema (Ubuntu) e nelle mie ricerche sul web. Sembra che l'abbiano chiarito, forse per Java 8 :) – nealmcb

2

si hanno due opzioni per ottenere risposta alla vostra domanda:

a) ispezionare il codice sorgente di JDK. Spiacente, non sono riuscito a effettuare il google in 5 minuti.

b) scrivere una simulazione, eseguirla più volte e fare alcune osservazioni.

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

ed eseguirlo più volte:

indovinare
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 

Così istruita è che Java non utilizza un numero esatto, ma 2^n approssimazione del numero richiesto.

1

In un altro question relativo alla bandiera -Xmx, Runtime.getRuntime().maxMemory() viene utilizzato per mostrare la dimensione corrente. Si noti inoltre che lo -Xmx1024m e lo -Xmx1g generano un output identico, a indicare che i numeri hanno potenze pari a due anziché dieci.

Notare la differenza tra totalMemory() e maxMemory().
What are Runtime.getRuntime().totalMemory() and freeMemory()?

+0

La domanda a cui fai riferimento è azzeccata! Guarda in particolare [class MemTest di Alex] (http: // stackoverflow.it/a/23702224/507544) lì, per una contabilità completa della memoria non heap (compresi Code Cache e Perm gen pool) vs memoria heap (inclusi Eden Space, Survivor space e Tenured gen pools) – nealmcb