2015-09-30 6 views
9

И вообще, являются ли единицы, используемые для опций -Xmx, -Xms и -Xmn («k», «M» и «G» или менее стандартные возможности «K», «m» или «g») Binary prefix кратность (т. е. мощности 1024), или они обладают мощностью 1000?Имеет ли java -Xmx1G 10^9 или 2^30 байт?

В руководствах указывается, что они представляют килобайты (кБ), мегабайты (МБ) и гигабайты (ГБ), предполагая, что они имеют мощность 1000, как определено в исходной системе SI. Мои неофициальные тесты (что я не очень уверен в этом) предлагают, чтобы они действительно были kibibytes (kiB), mebibytes (MiB) и gibibytes (GiB), все мощности 1024.

Так что это правильно? Например. какой Java-код будет показывать текущий размер?

Использование кратных 1024 не удивительно для размеров ОЗУ, поскольку оперативная память обычно физически выкладывается путем удвоения аппаратных модулей. Но использование единиц четким и стандартным образом становится все более важным, поскольку мы достигаем больших и больших полномочий, поскольку потенциал для путаницы растет. Единица «t» также принимается моей JVM, а 1 TiB на 10% больше, чем 1 ТБ.

Примечание: если они действительно являются двоичными кратными, я предлагаю обновить документацию и пользовательские интерфейсы, чтобы быть предельно ясными относительно этого, с примерами, такими как «. Добавить букву k или K, чтобы указать кибиты (1024 байта) или m или M, чтобы указать mebibytes (1048576 bytes) ". Это подход, принятый, например, в Ubuntu: UnitsPolicy - Ubuntu Wiki.

Примечание: для получения дополнительной информации о том, какие параметры используются, см., Например, java - What are the Xms and Xmx parameters when starting JVMs?.

+0

@ElliottFrisch В основном я задаю вопрос, ища окончательный ответ. Предложение документации просто предназначено для большей ясности в отношении того, с чем я запутался. – nealmcb

ответ

17

Короткий ответ: Все размеры памяти, используемые аргументы командной строки JVM указаны в традиционных бинарных единицах, где килобайт составляет 1024 байт, а остальные увеличиваются полномочия 1024.

Длинный ответ:

This documentation page on the command line arguments говорит следующее относится ко всем аргументам, принимающих размеры памяти:

Например, чтобы установить размер до 8 Гб, вы можете указать либо 8g, 8192m, 8388608k , или 8589934592 в качестве аргумента.

Для -Xmx, это дает следующие конкретные примеры:

Следующие примеры показывают, как установить максимально допустимый размер выделяемой памяти до 80 МБ с использованием различных устройств:

-Xmx83886080
-Xmx81920k
-Xmx80m

Прежде чем я подумал проверить документацию (предположил, что у вас уже есть?), Я проверил источник HotSpot и обнаружил, что значения памяти анализируются в src/share/vm/runtime/arguments.cpp с помощью функции atomull (которая, как представляется, обозначает «ASCII в память, без знака долго долго "):

// 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; 
    } 
} 

Эти константы K, M, G определены в src/share/vm/utilities/globalDefinitions.hpp:

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

Все это подтверждает документацию, за исключением того, что поддержка для суффикса T для терабайт, по-видимому, был добавлен позже и вообще не документирован.

Не обязательно использовать единичный множитель, поэтому, если вы хотите один миллиард байт, вы можете написать -Xmx1000000000. Если вы используете множитель, они двоичные, поэтому -Xmx1G означает 2 байт или одну палку o 'RAM.

(Это не удивительно, потому что Java предшествует попытке IEC ретроактивно переопределять существующие слова. Путаница могла бы быть сохранена, если бы МЭК просто советовал устранить неоднозначность блоков памяти с помощью классификаторов «двоичный» и «десятичный» иногда раз их смысл не ясен. Например, двоичные гигабайты (GB) = 1024 байт, и десятичные гигабайты (GB) = 1000 байт. Но нет, они переопределили слова, которые все уже использовали, неизбежно взорвались путаницы и leavi Мы застряли в этих клоунских терминах «гиббите», «тебибите» и остальном. О, Боже, пощади нас.)

+2

Спасибо, что нашли код ! Очень ясно. Но я должен отметить, что именно компьютерные люди переопределили ранее недвусмысленные термины, которые были старше двух веков. Для МЭК держать их так, как они были использованы так долго, и предоставить новые термины для новых единиц, делает для меня всевозможные соображения. MiB намного менее громоздкий и гораздо более легко отформатированный, переведенный и т. Д., Чем «бинарный мегабайт» или «MB_2». – nealmcb

+0

Спасибо, что нашли эту документацию. В нем есть более четкие примеры для разъяснения их использования MB и GB, чем документация, которую я нашел в своей системе (Ubuntu) и в моих веб-поисках. Похоже, они разъяснили это, возможно, для Java 8 :) – nealmcb

2

У вас есть два варианта, чтобы получить ответ на свой вопрос:

а) инспектировать исходный код JDK. Извините, я не смог отправить это через 5 минут.

b) написать симуляцию, запустить ее несколько раз и сделать некоторые наблюдения.

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

и запустить его несколько раз:

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 

Так догадка является то, что Java использует не точное число, но 2^п приближение числа вы просили.

1

В другом question относительно флага -Xmx, Runtime.getRuntime().maxMemory() используется для отображения текущего размера. Также отмечается, что -Xmx1024m и -Xmx1g приводят к идентичному выходу, что указывает на то, что числа имеют две, а не десять.

Обратите внимание на разницу между totalMemory() и maxMemory().
What are Runtime.getRuntime().totalMemory() and freeMemory()?

+0

Вопрос, на который вы ссылаетесь, находится на месте! Проверьте, в частности, [класс MemTest by Alex] (http: // stackoverflow.com/a/23702224/507544), там для полного учета памяти без кучи (в том числе кодов Cache и Perm gen) против памяти кучи (включая пространство Eden Space, Survivor и пулы Tenured gen) – nealmcb