Java память накладных расходов
Вопрос
Я хотел бы спросить о накладных расходах памяти в Java, у меня есть большой арайлист (61 770 предметов), и пытаюсь рассчитать количество памяти, предпринимаемое каждым элементом (подсчет объекта и его ArrayList), профилируя приложение, которое я получаю это После того, как все данные загружены, куча занимает ~ 25 МБ. Когда ArrayList имеет только 2 предмета, куча занимает ~ 1 МБ, так примерно:
(24 * 1024 * 1024) / 61,768 = 407 байтов.
Однако, Когда я считаю поля каждого объекта, я получаю 148 байтов (не включая ArrayList, и предполагая INT = 4, Float = 4, ссылку = 4), мне интересно узнать, откуда пришли все эти дополнительные байты ...
Я могу догадаться, что поскольку объекты, которые я хранят в ArrayList, реализует интерфейс, они хранят дополнительные значения, возможно, VM хранит функцию функции 4byse для каждого реализованного метода? Интерфейс, который они реализуют, имеют 20 функций, так и 80 байтов, на общую сумму 228 байтов, все еще не близко к измерению 400 байтов.
Любая помощь будет оценена.
Вау, спасибо за все великие ответы.
@Bolo: Спасибо за ссылку, с этим классом я измеряю ~ 350 байт на объект, поэтому я могу меньше подтвердить источник большого использования памяти.
@ Yuval A: Спасибо за эту презентацию, ценный источник информации.
@UKKO: точка отметил.
@Jayan: Прямо сейчас профилировщик NetBeans дает мне ошибки, когда я стараюсь бросить кучу, попробую позже.
Решение
Эти результаты не удивительны. JVM добавляет огромное количество накладных расходов на каждый объект.
Об одновременно вдвое больше ожидаемого размера для одного объекта, из-за накладных расходов памяти JVM, не редкость.
Эта презентация Имеет замечательный, подробный, объяснение и обзор различных использований памяти памяти структуры данных в Java.
Другие советы
ArrayList IST в основном больше, чем количество элементов. Использовать getCapacity()
Чтобы получить текущий размер базового массива.
Большая проблема с вашим подходом - это взаимодействие с сборщиком мусора. Он в основном делает любой тест, как вы предложили совершенно непрозрачную снаружи.
Как мыслительный эксперимент, если вы хотели сделать это, вы должны
- Выгоните свой JVM и сделайте пару глобальных GC, чтобы получить все мусор
- Измерьте размер кучи и понятие Java о том, сколько у него свободное пространство.
- Запустить свой тест
- GC пару раз
- Повторить измерения от шага № 2
После всего этого и немного математики вы будете ближе, но все еще не правы. Единственным реальным решением является фактически просить, как упомянуто, как другие люди. Или понять это от знания о реализации.
Память, потребляемая ArrayList, немного расплывчато.
Возьмите кучу дамп процесса на соответствующем этапе - после того, как значения полностью назначены. Затем используйте инструменты, такие как анализатор памяти (от Eclipse).
Вы заполняете находятся мелкие и сохраненные размеры кучи.
Как сбоку, так как вы точно знаете, сколько объектов будет в вашем арайлисте, почему бы не просто использовать массив []? Будет ли количество объектов в там изменить?