2010-04-27 5 views
4

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

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

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

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

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


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

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

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

@Ukko: указанный пункт.

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

+3

Эта статья может быть вам полезна: http://www.javaworld.com/javaworld/javatips/jw-javatip130.html – Bolo

+0

Если вы начинаете с нового ArrayList (61770) вместо, например, нового ArrayList (), а затем пусть это автоматически изменится, вы также получите разные накладные расходы. Вы установили правильный размер перед проверкой использования памяти? – extraneon

+0

@flamealpha: 61 770 невелик :) У меня есть HashMap настолько большой, что они приносят большинство систем на колени ... Вот почему я заменил их на * TIntIntHashMap от Trove *, которые просто * так * намного больше памяти/скорость-эффективность :) Увы, он работает только с примитивами: -/ – SyntaxT3rr0r

ответ

4

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

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

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

+0

извините, но он не работает – Gattsu

1

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

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

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

2

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

2

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

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

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

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

0

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

+0

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