Затраты памяти Java - PullRequest
       29

Затраты памяти Java

4 голосов
/ 27 апреля 2010

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

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

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

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

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


Ух, спасибо за все великолепные ответы.

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

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

@ Укко: точка отмечена.

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

Ответы [ 5 ]

6 голосов
/ 27 апреля 2010

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

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

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

2 голосов
/ 27 апреля 2010

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

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

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

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

2 голосов
/ 27 апреля 2010

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

1 голос
/ 27 апреля 2010

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

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

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

0 голосов
/ 27 апреля 2010

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

...