Накладные расходы памяти Java

Я хотел бы спросить о накладных расходах памяти в java, у меня есть большой ArrayList (61 770 элементов) и я пытаюсь рассчитать объем памяти, занимаемый каждым элементом (считая объект и его запись в ArrayList), профилируя приложение, я получаю это после загрузки всех данных куча занимает ~25Мб. когда в ArrayList всего 2 элемента, куча занимает ~ 1 МБ, поэтому примерно:

(24*1024*1024)/61 768 = 407 байт.

однако, когда я подсчитываю поля каждого объекта, я получаю 148 байт (не включая ArrayList и предполагая, что int=4,float=4,reference=4), мне любопытно узнать, где откуда взялись все эти дополнительные байты...

я могу предположить, что, поскольку объекты, которые я храню в ArrayList, реализуют интерфейс, они хранят дополнительные значения, может быть, виртуальная машина хранит 4-байтовый указатель на функцию для каждого реализованного метода? интерфейс, который они реализуют, имеет 20 функций, так что это еще 80 байтов, всего 228 байтов, что все еще не близко к измеренным 400 байтам.

любая помощь будет оценена.


вау, спасибо за все отличные ответы.

@Bolo: спасибо за ссылку, с этим классом я измеряю ~ 350 байт на объект, поэтому я могу как минимум подтвердить источник большого использования памяти.

@Yuval A: спасибо за эту презентацию, ценный источник информации.

@Ukko: пункт отмечен.

@Jayan: прямо сейчас профилировщик NetBeans выдает мне ошибки, когда я пытаюсь сбросить кучу, попробую позже.


person user326841    schedule 27.04.2010    source источник
comment
Эта статья может быть вам полезна: javaworld.com/javaworld/javatips/jw- javatip130.html   -  person Bolo    schedule 27.04.2010
comment
Если вы начнете с нового ArrayList(61770) вместо, например, нового ArrayList(), а затем разрешите ему автоматическое изменение размера, вы также получите другие накладные расходы. Вы установили правильный размер перед проверкой использования памяти?   -  person extraneon    schedule 27.04.2010
comment
@flamealpha: 61 770 невелико :) У меня есть HashMap‹Integer,Integer›, настолько большие, что они ставят большинство систем на колени... Вот почему я заменил их на TIntIntHashMap от Trove, который просто так гораздо эффективнее по памяти/скорости :) Увы, это работает только с примитивами :-/   -  person SyntaxT3rr0r    schedule 27.04.2010


Ответы (5)


Эти результаты не удивительны. JVM добавляет огромное количество накладных расходов к каждому объекту.

Примерно в два раза больше ожидаемого размера для одного объекта из-за накладных расходов на память JVM не редкость.

Эта презентация имеет прекрасный, -глубина, объяснение и обзор использования памяти различных структур данных в Java.

person Yuval Adam    schedule 27.04.2010

ArrayList обычно больше, чем количество элементов. Используйте getCapacity(), чтобы получить текущий размер базового массива.

person ZeissS    schedule 27.04.2010

Большой проблемой вашего подхода является взаимодействие со сборщиком мусора. По сути, это делает любой тест, который вы предложили, полностью непрозрачным снаружи.

В качестве мысленного эксперимента, если вы хотите сделать это, вы должны

  1. запустите свою JVM и сделайте пару глобальных сборщиков мусора, чтобы удалить весь хлам
  2. Измерьте размер кучи и представление Java о том, сколько у нее свободного места.
  3. Запустите свой тест
  4. ГК пару раз
  5. Повторите измерения с шага № 2.

После всего этого и немного математики вы будете ближе, но все же не правильно. Единственное реальное решение - на самом деле спросить реализацию, как упоминали другие люди. Или понять это из знания реализации.

person Ukko    schedule 27.04.2010

Память, потребляемая arraylist, немного расплывчата.

Сделайте дамп кучи процесса на соответствующем этапе - после того, как значения будут полностью присвоены. Затем используйте такие инструменты, как анализатор памяти (из eclipse).

Вы заполняете мелкие и сохраненные размеры кучи.

person Jayan    schedule 27.04.2010

В качестве примечания: поскольку вы точно знаете, сколько объектов будет в вашем ArrayList, почему бы просто не использовать массив []? Изменится ли там количество предметов?

person Dean J    schedule 27.04.2010
comment
это всего лишь пример, точное количество загружаемых элементов не предопределено, меня больше беспокоит накладные расходы памяти объекта, на который указывает массив. - person user326841; 27.04.2010