Как сделать память вашего Java-приложения эффективной? - PullRequest
17 голосов
/ 25 апреля 2009

Как оптимизировать использование размера кучи в приложении, в котором имеется много (миллионы) долгоживущих объектов? (большой кеш, загрузка большого количества записей из БД)

  • Используйте правильный тип данных
    • Избегайте java.lang.String для представления других типов данных
  • Избегайте дублирования объектов
    • Использовать перечисления, если значения известны заранее
    • Использовать пулы объектов
    • String.intern () (хорошая идея?)
  • Загружать / хранить только нужные вам объекты

Я ищу ответы на вопросы общего программирования или Java. Нет переключателя компилятора.

Edit:

Оптимизировать представление в памяти POJO, которое может появляться в куче миллионы раз.

Варианты использования

  • Загрузка огромного CSV-файла в память (преобразованного в POJO)
  • Использование hibernate для извлечения миллионов записей из базы данных

Резюме ответов:

  • Использовать шаблон в навесе
  • Копировать при записи
  • Вместо загрузки 10M объектов с 3 свойствами, более эффективно иметь 3 массива (или другую структуру данных) размером 10M? (Может быть, трудно манипулировать данными, но если у вас действительно мало памяти ...)

Ответы [ 11 ]

20 голосов
/ 25 апреля 2009

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

Вы можете посмотреть на изменение представления ваших данных, особенно если ваши объекты маленькие. Например, вы можете представить таблицу данных в виде серии столбцов с массивами объектов для каждого столбца, а не по одному объекту в строке. Это может сэкономить значительные накладные расходы для каждого объекта, если вам не нужно представлять отдельную строку. например таблица с 12 столбцами и 10 000 000 строк может использовать 12 объектов (по одному на столбец), а не 10 миллионов (по одному на строку)

17 голосов
/ 25 апреля 2009

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

  • Используйте шаблон в наименьшем весе везде возможно.
  • Кеширование на диск. Есть многочисленные кеш-решения для Java.
  • Есть некоторые споры относительно того, String.intern - хорошая идея. Увидеть здесь для вопроса re. String.intern () и количество споры о его пригодности.
  • Используйте мягкий или слабый ссылки для хранения данных, которые вы можете воссоздать / перезагрузить по требованию. Увидеть здесь о том, как использовать софт ссылки с методами кеширования.

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

11 голосов
/ 25 апреля 2009

Обеспечьте хорошую нормализацию вашей объектной модели, не дублируйте значения.

Гм, и, если бы это были только миллионы объектов, я думаю, я бы просто выбрал приличную 64-битную ВМ и много оперативной памяти;)

4 голосов
/ 26 апреля 2009

Обычные «профилировщики» не сильно вам помогут, потому что вам нужен обзор всех ваших «живых» объектов. Вам нужен анализатор дампа кучи. Я рекомендую Eclipse Memory анализатор .

Проверка на наличие дублированных объектов, начиная со строк. Проверьте, можете ли вы применять шаблоны, такие как flightweight, copyonwrite, lazy initialization (Google будет вашим другом).

3 голосов
/ 16 сентября 2011

Посмотрите на эту презентацию, связанную здесь. Он описывает использование в памяти общих объектов Java и примитивов и помогает понять, куда уходит вся дополнительная память.

Построение Java-приложений с эффективным использованием памяти: опыт и проблемы

2 голосов
/ 26 апреля 2009

Вы можете просто хранить меньше объектов в памяти. :) Используйте кэш, который разливается на диск, или используйте Terracotta для кластеризации вашей кучи (которая является виртуальной), позволяя неиспользуемым частям быть выгруженными из памяти и прозрачно возвращать их обратно.

1 голос
/ 29 апреля 2009

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

1 голос
/ 25 апреля 2009

Я хочу добавить кое-что к пункту, который сделал Питер Алреди (не могу прокомментировать его ответ :(), всегда лучше использовать профилировщик памяти (отметьте java memory profiler ), чем следовать интуиции В 80% случаев мы игнорируем обычную рутину, в ней есть некоторые проблемы. Также классы коллекций более подвержены утечкам памяти.

0 голосов
/ 06 апреля 2010
  1. Assign null значение для всех variables, которые no longer используются. Таким образом make it available for Garbage collection.
  2. De-reference the collections как только использование закончится, иначе GC не сместит их.
0 голосов
/ 29 апреля 2009

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

...