Статьи

Выравнивание памяти в C, C ++ и Java

Вы можете предположить, что уменьшение размера структуры или класса экономит тот же объем памяти. Однако из-за выравнивания памяти в распределителях памяти это может не иметь никакого значения или, возможно, большего, чем вы могли бы ожидать. Это потому, что объем зарезервированной памяти обычно кратен выравниванию памяти. Для Java и C это может 8 или 16 байтов.

 

Размер памяти зарезервирован

Эти тесты были выполнены в 64-битной программе на C (gcc 4.5.2) и 64 JVM (Oracle Java 7). В Java прямая память в значительной степени является оболочкой для malloc и свободной.

Б C malloc () зарезервировано Java ByteBuffer.allocateDirect ()
От 0 до 24 32 байта 32 байта + байтовый буфер
От 25 до 40 48 байтов 48 байт + байтовый буфер
С 41 по 56 64 байта 64 байта + байтовый буфер
57 до 72 80 байт 80 байт + байтовый буфер

Построение объектов — похожая история

 

Количество полей Класс C int
(куча / стек)
Класс C void *
(куча / стек)
 Класс Java 
 с int 
Java-класс
с объектными ссылками
1 32/16 байт 32/16 байт 16 байт 16 байт
2 32/16 байт 32/16 байт 24 байта 24 байта
3 32/16 байт 32/32 байта 24 байта 24 байта
4 32/16 байт 48/32 байта 32 байта 32 байта
5 32/32 байта 48/48 байт 32 байта 32 байта
6 32/32 байта 64/48 байт 40 байт 40 байт
7 48/32 байта 64/64 байта 40 байт 40 байт
8 48/32 байта 80/64 байта 48 байтов 48 байтов

Использование структуры / класса C в стеке более эффективно, чем другие подходы, по ряду причин, две из которых заключаются в том, что нет заголовка управления памятью и нет дополнительного указателя / ссылки (не показано в таблице).

JVM Sun / Oracle и OpenJDK 6 и 7 будут использовать 32-разрядные ссылки и 8-байтовую память, выровненную для поддержки до 32 ГБ (8 * 4 Г). Большинство JVM имеют размер менее 32 ГБ, что делает эту полезную оптимизацию. Примечание. Одной из причин того, что JVM обычно имеют размер от 1 до 4 ГБ, является то, что в худшем случае время полного GC обычно составляет 1 секунду на ГБ кучи, а время полного CG 30 секунд слишком велико для большинства приложений. Типичный способ обойти эту проблему полного времени GC — сохранить рабочий размер кучи до нескольких ГБ и использовать внешнюю базу данных или память без кучи «direct» и «memory mapped».

Другое решение для Java — использовать параллельный коллектор без пауз, такой как предоставляемый Azul. Они заявляют о превосходной масштабируемости за пределами 40 ГБ кучи, но открыто не перечисляют свои затраты;)

 

Почему это важно?

Скажем, у вас есть такой класс

 

class MyClass {
    int num;
    short value;
}

В C, сколько памяти экономится путем изменения num на short или сколько больше потребляется с этим делает long long . Скорее всего, ответ будет нулевым (если у вас нет такого массива). В Java это может иметь значение, так как размер выравнивания отличается. И наоборот, если класс / структура C имеет размер 16 или 17 байтов, он может сделать размер в стеке 16 или 32 байта. Точно так же, будучи 24 или 25 байтами, можно сделать размер используемого malloc 32 или 48 байтов.

Код

MemoryAlignment / main.cpp и
MemoryAlignment.java

 

От http://vanillajava.blogspot.com/2011/09/memory-alignment-in-cc-and-java.html